on master help sign in
.gitignore+3
since splitsnapshots
unifiedsplit
@@ -2,3 +2,6 @@ __pycache__/
2*.pyc
2*.pyc
3result
3result
4result-*
4result-*
5+
6+# Generated by tools/ship gen-tests; desk assembly regenerates it.
7+/tests/lib/jibb.hoon
LICENSEnew file+21
@@ -0,0 +1,21 @@
1+MIT License
2+
3+Copyright (c) 2026 the Jibb authors
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy
6+of this software and associated documentation files (the "Software"), to deal
7+in the Software without restriction, including without limitation the rights
8+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+copies of the Software, and to permit persons to whom the Software is
10+furnished to do so, subject to the following conditions:
11+
12+The above copyright notice and this permission notice shall be included in all
13+copies or substantial portions of the Software.
14+
15+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+SOFTWARE.
README.md+46−21
@@ -1,6 +1,6 @@
1# Jibb
1# Jibb
2
2
3−Jibb is a UI language for Urbit: a Hoon dialect with an indentation layout. Its design doc, [Jibb — an Elm-architecture UI language for Urbit](https://claude.ai/artifact/DMBr48qzi5z8hcwn2ccPBv), is the spec, and where this code and the doc disagree, the doc wins.
3+Jibb is a UI language for Urbit: a Hoon dialect with an indentation layout. Its design doc, [Jibb — an Elm-architecture UI language for Urbit](https://claude.ai/artifact/DMBr48qzi5z8hcwn2ccPBv), is the spec. Its copy in [docs/spec/](docs/spec/) records decisions the doc doesn't have yet, so until the doc is synced, that copy wins where it and the doc differ, and where this code and the spec disagree, the spec wins.
4
4
5Milestone 1 of the doc's eight, the parser and the `%jibb` mark, is done; milestone 2, types and prelude, is in progress. The type checker and Hoon importer are partial. [docs/](docs/) holds a copy of the doc's tabs, the status of each milestone, the open questions, a development guide, a map of the compiler, and the brief for milestone 2.
5Milestone 1 of the doc's eight, the parser and the `%jibb` mark, is done; milestone 2, types and prelude, is in progress. The type checker and Hoon importer are partial. [docs/](docs/) holds a copy of the doc's tabs, the status of each milestone, the open questions, a development guide, a map of the compiler, and the brief for milestone 2.
6
6
@@ -10,8 +10,8 @@ Milestone 1 of the doc's eight, the parser and the `%jibb` mark, is done; milest
10- `jibb/`: the `%jibb` desk, for the shared host (milestone 4).
10- `jibb/`: the `%jibb` desk, for the shared host (milestone 4).
11- `my-app/`: an example app desk built from the doc's worked examples.
11- `my-app/`: an example app desk built from the doc's worked examples.
12- `vendor/`: pinned copies of the base-dev and landscape files the desks need.
12- `vendor/`: pinned copies of the base-dev and landscape files the desks need.
13−- `tests/`: golden cases in `golden/<case>/`, and on-ship tests for the `-test` thread in `lib/jibb.hoon`.
13+- `tests/`: golden cases in `golden/<case>/`, test suites in `lib/` and their fixtures, for `tools/test-arms` and the ship's `-test` thread, and in `clay-fixtures/`, the threads `tools/clay-fixtures` runs and, in `clay-fixtures/desk/`, the Hoon files the `jibb-fixtures` desk adds to `my-app`. `lib/jibb.hoon`, which runs the golden cases on the ship, is generated.
14−- `tools/`: dev tooling: `golden`, `hoon` and `doc-blocks`, with their self-test in `testdata/`, `ship`, and `check`, which runs every check.
14+- `tools/`: dev tooling: `golden`, `test-arms`, `hoon` and `doc-blocks`, with their self-test in `testdata/`, `ship`, and `check`, which runs every check.
15- `docs/`: the doc's tabs as Markdown in `spec/`, the status, the open questions, the development guide, the compiler's map, and briefs for milestones in `prompts/`.
15- `docs/`: the doc's tabs as Markdown in `spec/`, the status, the open questions, the development guide, the compiler's map, and briefs for milestones in `prompts/`.
16
16
17## Building and checking with Nix
17## Building and checking with Nix
@@ -19,15 +19,15 @@ Milestone 1 of the doc's eight, the parser and the `%jibb` mark, is done; milest
19The flake (`flake.nix`, pinned by `flake.lock`) builds the desks and runs every check, with vere 4.6, Python 3, click and the brass pill pinned:
19The flake (`flake.nix`, pinned by `flake.lock`) builds the desks and runs every check, with vere 4.6, Python 3, click and the brass pill pinned:
20
20
21```
21```
22−nix build # result/my-app, result/jibb, result/jibb-dev: the desks
22+nix build # result/my-app, result/jibb, result/jibb-dev, result/jibb-fixtures: the desks
23nix flake check # every check: the eval group and, on Linux, the ship group on a fresh fake ~zod
23nix flake check # every check: the eval group and, on Linux, the ship group on a fresh fake ~zod
24nix develop # a shell with urbit, python3 and click, for running the tools by hand
24nix develop # a shell with urbit, python3 and click, for running the tools by hand
25nix build .#fakezod # a freshly booted fake ~zod pier (Linux)
25nix build .#fakezod # a freshly booted fake ~zod pier (Linux)
26```
26```
27
27
28−Jibb has no native binary: what it ships is desks, Hoon and Jibb source that a ship builds. So `nix build` writes the three desks exactly as `tools/ship sync` would commit them (it runs `tools/ship assemble`), and compiles `jibb.hoon` and `jibb-import.hoon` under `urbit eval` to check that they build.
28+Jibb has no native binary: what it ships is desks, Hoon and Jibb source that a ship builds. So `nix build` writes the four desks exactly as `tools/ship sync` would commit them (it runs `tools/ship assemble`), and compiles `jibb.hoon` and `jibb-import.hoon` under `urbit eval` to check that they build.
29
29
30−`nix flake check` builds that too, then runs `tools/check --group eval` and, on Linux, `tools/check --group ship` against a copy of a fake ~zod it boots from the pill. Everything runs in the Nix sandbox without network, so a check can't pass because of something on your machine. Each group is one build; a failure prints the failing checks' output, and a passing build keeps every check's log in its output. On four CPUs it took about 20 minutes, the two groups building side by side: 18 minutes for the eval group, most of it `type-todo-full-test`, and 10 for the ship group. To run a single check, use `nix develop -c tools/check <name>` (see [docs/development.md](docs/development.md#before-pushing)).
30+`nix flake check` builds that too, then runs `tools/check --group eval` and, on Linux, `tools/check --group ship` against a copy of a fake ~zod it boots from the pill. Everything runs in the Nix sandbox without network, so a check can't pass because of something on your machine. Each group is one build; a failure prints the failing checks' output, and a passing build keeps every check's log in its output. On four CPUs it takes about 10 minutes, the two groups building side by side: under 3 minutes for the eval group (it took 18 before `tools/test-arms` replaced a script per suite) and 10 for the ship group. To run a single check, use `nix develop -c tools/check <name>` (see [docs/development.md](docs/development.md#before-pushing)).
31
31
32Limits: the ship checks need Linux, since `tools/ship` finds the ship's processes in `/proc`, so on macOS `nix flake check` runs only the eval group. Only `x86_64-linux` has been tried; the flake also declares `aarch64-linux` and `aarch64-darwin`, the other platforms nixpkgs builds vere for.
32Limits: the ship checks need Linux, since `tools/ship` finds the ship's processes in `/proc`, so on macOS `nix flake check` runs only the eval group. Only `x86_64-linux` has been tried; the flake also declares `aarch64-linux` and `aarch64-darwin`, the other platforms nixpkgs builds vere for.
33
33
@@ -59,19 +59,7 @@ tools/hoon '(golden /a/b/jibb (crip "++ main view"))'
59tools/hoon --raw --cord src=tests/golden/foo/source.jibb 'tree:(golden /a/b/jibb src)'
59tools/hoon --raw --cord src=tests/golden/foo/source.jibb 'tree:(golden /a/b/jibb src)'
60```
60```
61
61
62−`tools/testdata/selftest` tests both tools against a stub library, and `tools/doc-blocks` against Markdown it writes. `tools/importer-test` compares the partial Hoon importer's fixture projections against their golden file. `tools/type-import-test`, `tools/type-import-overlap-test`, `tools/type-import-structural-test`, `tools/type-union-source-test`, `tools/type-union-alias-overlap-test`, `tools/type-full-overlap-test`, `tools/type-generic-recursion-test`, `tools/type-generic-construction-test`, `tools/type-generic-pattern-test`, `tools/type-deferred-test`, `tools/type-deferred-prepared-test`, `tools/type-deferred-resolver-test`, `tools/type-deferred-context-test`, `tools/type-empty-test`, `tools/type-cell-branch-test`, `tools/type-tlon-test`, `tools/type-mark-test`, `tools/type-poke-test` and `tools/type-api-paths-test` check importer/checker, prelude and partial API path analysis boundaries under eval; the ship suite runs the same fixtures.
62+`tools/testdata/selftest` tests `tools/golden` and `tools/hoon` against a stub library, `tools/test-arms` against the same library with suites it writes, and `tools/doc-blocks` against Markdown it writes.
63−
64−The focused `tools/type-page-main-test` fully checks the byte-identical static about page and direct blog/todo data pages through the real readers, with exact main types, downstream imports and fail-closed syntax/evidence controls; the same fixture runs on the fake ship. It does not render pages or execute requests.
65−
66−The focused `tools/type-buttons-test` fully checks the documented `labelled` and `wide` definitions and the unchanged module's exact source-located unresolved-`%add` error through detailed and legacy inference. The eval test and fake-ship arm share the valid source, schemes and error fixtures. It does not render or execute UI.
67−
68−The focused `tools/type-doc-examples-test` fully checks the import-only example with real Hoon readers and the card module, the `view-day` and `step` modules, and the `cmd`/`sub` molds at their prelude path through detailed and legacy inference. The same fixture runs on the fake ship.
69−
70−The focused `tools/type-theme-test` fully checks the byte-identical real theme against the exact prelude mold, including its exported type, structural downstream import, dark absent/present forms and malformed-field negatives under eval with a shared fake-ship arm. It does not check contrast, render themes or route fonts.
71−
72−The focused `tools/type-store-test` checks the byte-identical cart store and basket through detailed and legacy inference, exact main and derived schemes, structural imports, direct store watch evidence and rejection controls under eval with a shared fake-ship arm. It does not lower or execute stores, support multi-action declarations, or permit store requests in page loads.
73−
74−The focused `tools/type-program-main-test` checks the narrow closed, subscription-free `main` slice and its shared fake-ship fixture. `tools/type-program-init-test` checks transactional initializer recovery for a synthetic direct program, including exact exported and imported types and rejection boundaries. `tools/type-program-update-test` checks derived result context for an unannotated two-slot update, including a union/boolean branch, downstream types and fail-closed controls under eval with a shared fake-ship arm. `tools/type-program-watch-test` uses the real todo readers with synthetic program components to check one direct request value against merged API-source evidence and reject hand-built, indirect, parameterized, diff and ambiguous subscriptions. These are static checks only: they do not run an island or establish runtime watching. `tools/type-todo-full-test` additionally checks the byte-identical todo island through both full-module APIs, verifies its exact closed `main` type and structural downstream import, and runs rejection controls.
75
63
76### The doc's examples
64### The doc's examples
77
65
@@ -84,6 +72,43 @@ tools/doc-blocks Grammar.md Overview.md Core-language.md # fresh exports
84
72
85It matches each labelled block to the case whose `source.jibb` is the block's text plus a newline, and lists the blocks no case holds, each with a diff against the closest unmatched case, and the `doc-*` cases no block holds. Pass every tab with Jibb blocks, or the other tabs' cases count as stale. The exit status is 0 when every block has a case and every case a block, 1 when one doesn't, and 2 when the check can't run, for example because no block is labelled `jibb`.
73It matches each labelled block to the case whose `source.jibb` is the block's text plus a newline, and lists the blocks no case holds, each with a diff against the closest unmatched case, and the `doc-*` cases no block holds. Pass every tab with Jibb blocks, or the other tabs' cases count as stale. The exit status is 0 when every block has a case and every case a block, 1 when one doesn't, and 2 when the check can't run, for example because no block is labelled `jibb`.
86
74
75+## Test suites
76+
77+Each `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.
78+
79+```
80+tools/test-arms # every suite
81+tools/test-arms jibb-store 'jibb-program-*' # suites by name or glob
82+tools/test-arms --shard 2/4 # the second of four shards, balanced by measured cost
83+tools/test-arms --list # the suites and their arms; ", report" marks a golden report
84+tools/test-arms --report jibb-import # print a golden-report suite's report
85+tools/test-arms --update jibb-import # write it to the suite's expected file
86+```
87+
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`.
89+
90+A 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.
91+
92+The `jibb-dev` desk holds `my-app`'s sources under `/my-app`, without its desk files, so the suites below that check `my-app` files read them there, and a golden case that uses one links to it: `tests/golden/doc-overview-02-theme/source.jibb` is a symlink to `my-app/ui/theme.jibb`.
93+
94+`tools/test-arms --list` lists every suite, and [The test suites](docs/development.md#the-test-suites) in the development guide says what each one checks. Each suite it lists runs under eval and on the fake ship, with the same fixtures. The `jibb-import` suite compares the partial Hoon importer's fixture projections against their golden file. The suites `jibb-bridge`, `jibb-import-overlap`, `jibb-import-structural`, `jibb-union-source`, `jibb-union-alias-overlap`, `jibb-full-overlap-basic`, `jibb-full-overlap-graph`, `jibb-generic-recursion`, `jibb-generic-construction`, `jibb-generic-pattern`, `jibb-deferred`, `jibb-deferred-prepared`, `jibb-deferred-resolver`, `jibb-deferred-context`, `jibb-empty`, `jibb-cell-branch`, `jibb-tlon-bridge`, `jibb-mark-bridge`, `jibb-poke-bridge` and `jibb-api-paths` check importer/checker, prelude and partial API path analysis boundaries.
95+
96+`tests/lib/jibb-page-main.hoon` fully checks the byte-identical static about page and direct blog/todo data pages through the real readers, with exact main types, downstream imports and fail-closed syntax/evidence controls. It does not render pages or execute requests.
97+
98+`tests/lib/jibb-buttons.hoon` fully checks the documented `labelled` and `wide` definitions and the unchanged module's exact source-located unresolved-`%add` error through detailed and legacy inference, with the valid source, schemes and error fixtures in `tests/type-buttons/`. It does not render or execute UI.
99+
100+`tests/lib/jibb-doc-examples.hoon` fully checks the import-only example with real Hoon readers and the card module, the `view-day` and `step` modules, and the `cmd`/`sub` molds at their prelude path through detailed and legacy inference.
101+
102+`tests/lib/jibb-theme.hoon` fully checks the byte-identical real theme against the exact prelude mold, including its exported type, structural downstream import, dark absent/present forms and malformed-field negatives. It does not check contrast, render themes or route fonts.
103+
104+`tests/lib/jibb-store.hoon` checks the byte-identical cart store and basket through detailed and legacy inference, exact main and derived schemes, structural imports, direct store watch evidence and rejection controls. It does not lower or execute stores, support multi-action declarations, or permit store requests in page loads.
105+
106+`tests/lib/jibb-program-main.hoon` checks the narrow closed, subscription-free `main` slice. `tests/lib/jibb-program-init.hoon` checks transactional initializer recovery for a synthetic direct program, including exact exported and imported types and rejection boundaries. `tests/lib/jibb-program-update.hoon` checks derived result context for an unannotated two-slot update, including a union/boolean branch, downstream types and fail-closed controls. `tests/lib/jibb-program-watch.hoon` uses the real todo readers with synthetic program components to check one direct request value against merged API-source evidence and reject hand-built, indirect, parameterized, diff and ambiguous subscriptions. These are static checks only: they do not run an island or establish runtime watching. `tests/lib/jibb-todo-full.hoon` additionally checks the byte-identical todo island through both full-module APIs, verifies its exact closed `main` type and structural downstream import, and runs rejection controls.
107+
108+## Licence
109+
110+Jibb is under the MIT licence, in [LICENSE](LICENSE). Two kinds of files in it are other people's, under their own MIT licences: the files in `vendor/` are copies from urbit/urbit, whose licence is in [vendor/LICENSE-urbit.txt](vendor/LICENSE-urbit.txt), and the Tlon `/sur` files that `tests/` uses as importer fixtures come from tloncorp/tlon-apps, whose licence is in [tests/importer/tlon-license.txt](tests/importer/tlon-license.txt).
111+
87## Fake ship
112## Fake ship
88
113
89`tools/ship` runs the desks on a fake `~zod` at `/root/urbit/zod` (`--pier` or `$JIBB_PIER`). It needs Python 3 and click (`/root/src/tools/pkg/click/click`, or `--click`). The ship runs in the background, logging to `/root/urbit/zod.log`.
114`tools/ship` runs the desks on a fake `~zod` at `/root/urbit/zod` (`--pier` or `$JIBB_PIER`). It needs Python 3 and click (`/root/src/tools/pkg/click/click`, or `--click`). The ship runs in the background, logging to `/root/urbit/zod.log`.
@@ -103,7 +128,7 @@ tools/ship stop
103| `jibb` | `vendor/*`, then `jibb` |
128| `jibb` | `vendor/*`, then `jibb` |
104| `jibb-dev` | `vendor/*`, then `jibb-dev`, then `tests/`, with `tests/lib/jibb.hoon` generated, and `jibb/sys.kelvin` |
129| `jibb-dev` | `vendor/*`, then `jibb-dev`, then `tests/`, with `tests/lib/jibb.hoon` generated, and `jibb/sys.kelvin` |
105
130
106−The `jibb-dev` desk runs the golden cases on the ship, as `-test` arms. `tools/ship gen-tests` writes `tests/lib/jibb.hoon` from `tests/golden`: for each case it imports `source.jibb`, `tokens.txt` and `tree.txt` with `/*`, and its `test-` arm compares `golden:jibb` with them. Cases opted into `types.txt` also compare the partial inference output. Don't edit that file; `--check` says whether it's up to date. `tools/ship test` regenerates it, syncs the desk and runs `-test /=jibb-dev=/tests`, printing each case's OK, FAILED or CRASHED and the reason. It exits 0 only when every case passes.
131+The `jibb-dev` desk runs the golden cases on the ship, as `-test` arms. `tools/ship gen-tests` writes `tests/lib/jibb.hoon` from `tests/golden`: for each case it imports `source.jibb`, `tokens.txt` and `tree.txt` with `/*`, reading a `source.jibb` that links to a `my-app` file from `/my-app`, and its `test-` arm compares `golden:jibb` with them. Cases opted into `types.txt` also compare the partial inference output. The file is generated, not committed (review question 32): desk assembly writes it afresh, and `.gitignore` lists it. `tools/ship test` regenerates it, syncs the desk and runs `-test /=jibb-dev=/tests`, printing each case's OK, FAILED or CRASHED and the reason. It exits 0 only when every case passes.
107
132
108```
133```
109tools/ship test # the library and tests/golden
134tools/ship test # the library and tests/golden
@@ -115,7 +140,7 @@ A sync with nothing to commit takes about 2 s. A commit adds 3 to 10 s, and 300
115
140
116`tools/ship check-commit` proves that `|commit` stores `.jibb` files. It syncs `my-app`, reads every `/ui` file back with `%cx`, byte for byte, and converts `%jibb` to `%mime` and `%txt` and back. It commits half-written files, then deletes them. It merges a file that two desks changed on different lines, and checks that changes to the same line conflict. It can be rerun, and it leaves the two scratch desks it merges with (`%jibb-check-ours` and `%jibb-check-theirs`) holding only what `|new-desk` gives, unmounted.
141`tools/ship check-commit` proves that `|commit` stores `.jibb` files. It syncs `my-app`, reads every `/ui` file back with `%cx`, byte for byte, and converts `%jibb` to `%mime` and `%txt` and back. It commits half-written files, then deletes them. It merges a file that two desks changed on different lines, and checks that changes to the same line conflict. It can be rerun, and it leaves the two scratch desks it merges with (`%jibb-check-ours` and `%jibb-check-theirs`) holding only what `|new-desk` gives, unmounted.
117
142
118−`tools/clay-fixtures` syncs `my-app`, builds its example `/sur` files and marks through Clay, and checks selected types read from the compiled graphs and passed to the partial checker. It compares the results with golden files under `tests/clay-fixtures/`.
143+`tools/clay-fixtures` syncs `my-app` and `jibb-fixtures`, builds their example `/sur` files and marks through Clay, and checks selected types read from the compiled graphs and passed to the partial checker. It compares the results with golden files under `tests/clay-fixtures/`.
119
144
120For anything else:
145For anything else:
121
146
docs/README.md+7−4
@@ -6,17 +6,20 @@ The current full-module checker also has a narrow static/data-page slice, docume
6
6
7| File | What it holds |
7| File | What it holds |
8| --- | --- |
8| --- | --- |
9−| [spec/](spec/) | The doc's tabs, as Markdown |
9+| [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 |
11| [open-questions.md](open-questions.md) | Questions still open: the plan's, the grammar's, and those milestone 2 raises |
11| [open-questions.md](open-questions.md) | Questions still open: the plan's, the grammar's, and those milestone 2 raises |
12| [development.md](development.md) | Setting up a machine, the ground rules, the checks to run before pushing |
12| [development.md](development.md) | Setting up a machine, the ground rules, the checks to run before pushing |
13| [compiler.md](compiler.md) | A map of `jibb-dev/lib/jibb.hoon`: its API, data, errors and printed formats |
13| [compiler.md](compiler.md) | A map of `jibb-dev/lib/jibb.hoon`: its API, data, errors and printed formats |
14| [prelude-inventory.md](prelude-inventory.md) | Working source audit for the prelude's exported inventory |
14| [prelude-inventory.md](prelude-inventory.md) | Working source audit for the prelude's exported inventory |
15| [prompts/milestone-2.md](prompts/milestone-2.md) | A brief for the developer who builds milestone 2, types and prelude |
15| [prompts/milestone-2.md](prompts/milestone-2.md) | A brief for the developer who builds milestone 2, types and prelude |
16| [prompts/drop-union-rune.md](prompts/drop-union-rune.md) | The completed brief for dropping `$?`, as decided on 2026-10-30, before milestone 2 |
16| [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 |
17| [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 |
18| [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 |
18| [reviews/2026-11-02-questions.md](reviews/2026-11-02-questions.md) | The 45 decisions that review raises, with options and recommendations |
19| [reviews/2026-11-02-questions.md](reviews/2026-11-02-questions.md) | The 45 decisions that review raises, with options and recommendations |
19| [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 |
20| [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 |
20
23
21## The spec
24## The spec
22
25
@@ -27,14 +30,14 @@ The current full-module checker also has a narrow static/data-page slice, docume
27| [spec/overview.md](spec/overview.md) | Jibb — an Elm-architecture UI language for Urbit: the language, the stages, the mark, the host, worked examples |
30| [spec/overview.md](spec/overview.md) | Jibb — an Elm-architecture UI language for Urbit: the language, the stages, the mark, the host, worked examples |
28| [spec/grammar.md](spec/grammar.md) | Grammar: lexical rules, literals, runes, imports, modules, molds, tag resolution, patterns, the EBNF |
31| [spec/grammar.md](spec/grammar.md) | Grammar: lexical rules, literals, runes, imports, modules, molds, tag resolution, patterns, the EBNF |
29| [spec/core-language.md](spec/core-language.md) | Core language: the untyped language between the checker and both backends |
32| [spec/core-language.md](spec/core-language.md) | Core language: the untyped language between the checker and both backends |
30−| [spec/decisions.md](spec/decisions.md) | Decisions: every choice, with the date it was made |
33+| [spec/decisions.md](spec/decisions.md) | Decisions: every choice, with the date it was made and whether the doc has it yet, and the settled milestone 2 questions |
31| [spec/implementation-plan.md](spec/implementation-plan.md) | Implementation plan: the eight milestones, ground rules, architecture, risks, open questions |
34| [spec/implementation-plan.md](spec/implementation-plan.md) | Implementation plan: the eight milestones, ground rules, architecture, risks, open questions |
32
35
33The doc has a sixth tab, "Loom on Urbit", which is empty, so it has no file.
36The doc has a sixth tab, "Loom on Urbit", which is empty, so it has no file.
34
37
35The overview's pipeline diagram, "Jibb pipeline · source to browser in three stages", is embedded content, so the export holds only a placeholder line for it under Architecture. The doc shows it.
38The overview's pipeline diagram, "Jibb pipeline · source to browser in three stages", is embedded content, so the export holds only a placeholder line for it under Architecture. The doc shows it.
36
39
37−The two copies can diverge. Sync the repository decisions to the Claude document before refreshing this copy, then export each tab as Markdown again (in a Claude session, the Claude Docs connector's `export` gives each tab's Markdown), replace the files, and run:
40+The two copies can diverge, and until they are synced, this copy wins (review question 42). Sync the repository decisions to the Claude document before refreshing this copy: the rows that decisions.md's Synced column marks No or Check, and its settled milestone 2 questions. Then export each tab as Markdown again (in a Claude session, the Claude Docs connector's `export` gives each tab's Markdown), replace the files, and run:
38
41
39```
42```
40git diff docs/spec # what changed in the doc
43git diff docs/spec # what changed in the doc
docs/compiler.md+27−17
@@ -56,7 +56,9 @@ The core is split into chapters, `+| %name`, in this order:
56| `%span-check` | `+check-spans`, which `+golden` runs on every tree, and `+check-spans-test` |
56| `%span-check` | `+check-spans`, which `+golden` runs on every tree, and `+check-spans-test` |
57| `%type-inference` | The initial inference fragment and its unification helpers; not yet a module type checker |
57| `%type-inference` | The initial inference fragment and its unification helpers; not yet a module type checker |
58
58
59−The inference fragment supports fixed auras, unrestricted `@`, one-way widening into it and toward aura-family ancestors, generic variables and gates, faced and unfaced cells, cell sample binders, known record field reads, a cell pattern of two or more binders, a complete two-arm loobean branch, a complete two-arm unit-shaped branch, closed local mold aliases and acyclic forward value references. For a supported single syntactic top-level recursive gate, the checker infers the sample first and uses that exact sample, including its field faces, in a monomorphic self placeholder. The completed body must unify with the placeholder before the gate is generalized; incompatible recursive arguments can report the call and argument sites. Uses of generalized top-level definitions instantiate their schemes independently. For a complete loobean branch with one direct self-call arm, the checker can infer the other arm independently and use its closed, fully resolved type to seed the recursive result; it then checks the whole body. Open or pending base types do not seed the result, and other branch shapes still depend on the existing partial inference. A supported single local recursive gate also uses a monomorphic self reference while its body is checked, then generalizes variables free of its enclosing environment; captured variables remain shared. Acyclic local value definitions can refer forward. 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. Some proven non-gate value cycles are diagnosed; other mixed gate/value cycles, polymorphic recursion, unresolved literal constraints and unresolved branch joins remain unsupported. Acyclic simple local mold aliases can also refer forward, and are scoped to the body, not its gate's sample. Nonrecursive generic aliases of supported molds can be applied at exact arity, including locally and through library interfaces; their parameters are lexical. Closed, provably disjoint nonrecursive unions and tagged single-case molds support contextual term values, `~` and `|=%tag` constructors. Literal heads compare by their runtime noun, so `|=%$` can construct an explicit null-, loobean-zero- or term-zero-headed case. Equal heads with distinct payloads can be selected when exactly one payload fit is proven; unknown or ambiguous alternatives remain unsupported. Unresolved tags and nulls remain pending, with distinct partial-inference diagnostics. Nonrecursive top-level generic union molds with provably disjoint cases also support contextual tags and constructors at exact arity; their arguments are retained through generalization and supported library interfaces. Nonrecursive generic aliases can reorder, repeat or omit parameters while preserving a supported union’s origin, including through local scopes and library interfaces. Generic unions declared directly inside a body and recursive molds outside the source-proven slices described below remain unsupported. A directly known named union can instantiate an unconstrained generic gate sample while retaining its origin, generic arguments and faces. Unnamed, pending-tag, recursive, unknown-atom and variable-bound union origins 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. A differing-variable face constraint remains unsupported. When inference forces two distinct explicitly written capitals equal, it reports both source sites; forcing a capital to a concrete type remains unsupported in this fragment. It can infer and generalize atom constraints arising from explicit capitals or bare sample binders, preserve those constraints through aliases, instantiate them independently, and print multiple constraints. Unresolved decimal variables default to `@ud` for inferred types without gates; defaulting inside gate types and other constraint cases remain incomplete. It does not yet check a module, complete imports, general patterns, general deferred constraints, recursive molds, dependency cycles or most errors with both conflicting excerpts. Definite cast and call mismatches, incompatible branches and overlapping union cases report both sites and excerpts. Concrete branch results can join at an explicitly present parent aura or `@`. Some known tuple and record positions acquire matching faces; other variable-dependent face merges, general branch tag context and ambiguous call-result propagation remain unsupported; function compatibility involving nested `@` and variable-dependent joins remain unsupported except for equal types and the source-bound gate-sample proof below. For a single recursive gate outside a group, the reporting path repeats inference rather than instantiating its generalized interface inside its own body; a group report uses its stored schemes. This adds work, and the current dependency pass can take quadratic time on long forward chains; the milestone's speed target remains unverified. A separate conservative pass reports unions whose cases are provably disjoint or overlapping and leaves other cases unresolved; it does not claim the mold is checked. Unsupported forms are reported as such, and the partial output says the module has not been checked.
59+The inference fragment supports fixed auras, unrestricted `@`, one-way widening into it and toward aura-family ancestors, generic variables and gates, faced and unfaced cells, cell sample binders, known record field reads, a cell pattern of two or more binders, a complete two-arm loobean branch, a complete two-arm unit-shaped branch, closed local mold aliases and acyclic forward value references. For a supported single syntactic top-level recursive gate, the checker infers the sample first and uses that exact sample, including its field faces, in a monomorphic self placeholder. The completed body must unify with the placeholder before the gate is generalized; incompatible recursive arguments can report the call and argument sites. Uses of generalized top-level definitions instantiate their schemes independently. For a complete loobean branch with one direct self-call arm, the checker can infer the other arm independently and use its closed, fully resolved type to seed the recursive result; it then checks the whole body. Open or pending base types do not seed the result, and other branch shapes still depend on the existing partial inference. A supported single local recursive gate also uses a monomorphic self reference while its body is checked, then generalizes variables free of its enclosing environment; captured variables remain shared. Acyclic local value definitions can refer forward. When the remaining local definitions stop making progress and no cyclic group applies, the earliest of them whose definite error no order of the siblings could change reports it; otherwise the generic message remains. A definite error names sites, except an uncertain type hole, which names its site but is unsupported. A sibling can change another's result through a type variable the locals share, such as one in an untyped sample of the enclosing gate: a sibling's cast of the sample to `!!` makes every cast of it fit. So the error of a local that names no sibling and nothing whose type has a shared variable always counts. Another local's error counts only if no sibling had bound or refined a shared variable when it was tried and every other waiting definition also failed with sites, since one that waits without them, on a checker limit, a pending tag or its own nested stall, might in another order constrain the shared variable. In that case every definition is inferred against the same state in every order. A definition that infers but is then rejected as unsupported, such as for an uncertain type hole or a capital forced to a concrete type, reports its own message. Errors found while a cyclic group is inferred together are dropped, so a mutual group whose error comes after the call to its partner keeps the generic message. 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. Top-level definitions are inferred in the order of the same graph's components, dependencies first, so a chain of forward references resolves in one pass; the checker repeats passes while one adds a definition, as a fallback. Supported local mutually recursive gate groups also use shared monomorphic placeholders and generalize only after the group checks, preserving captured outer variables. Some proven non-gate value cycles are diagnosed; other mixed gate/value cycles, polymorphic recursion, unresolved literal constraints and unresolved branch joins remain unsupported. Acyclic simple local mold aliases can also refer forward, and are scoped to the body, not its gate's sample. Nonrecursive generic aliases of supported molds can be applied at exact arity, including locally and through library interfaces; their parameters are lexical. Closed, provably disjoint nonrecursive unions and tagged single-case molds support contextual term values, `~` and `|=%tag` constructors. Literal heads compare by their runtime noun, so `|=%$` can construct an explicit null-, loobean-zero- or term-zero-headed case. Equal heads with distinct payloads can be selected when exactly one payload fit is proven; unknown or ambiguous alternatives remain unsupported. Unresolved tags and nulls remain pending, with distinct partial-inference diagnostics. Nonrecursive top-level generic union molds with provably disjoint cases also support contextual tags and constructors at exact arity; their arguments are retained through generalization and supported library interfaces. Nonrecursive generic aliases can reorder, repeat or omit parameters while preserving a supported union’s origin, including through local scopes and library interfaces. Generic unions declared directly inside a body and recursive molds outside the source-proven slices described below remain unsupported. A directly known named union can instantiate an unconstrained generic gate sample while retaining its origin, generic arguments and faces. Unnamed, pending-tag, recursive, unknown-atom and variable-bound union origins 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. A differing-variable face constraint remains unsupported. When inference forces two distinct explicitly written capitals equal, it reports both source sites; forcing a capital to a concrete type remains unsupported in this fragment. It can infer and generalize atom constraints arising from explicit capitals or bare sample binders, preserve those constraints through aliases, instantiate them independently, and print multiple constraints. Unresolved decimal variables default to `@ud` for inferred types without gates; defaulting inside gate types and other constraint cases remain incomplete. It does not yet check a module, complete imports, general patterns, general deferred constraints, recursive molds, dependency cycles or most errors with both conflicting excerpts. Definite cast and call mismatches, incompatible branches and overlapping union cases report both sites and excerpts. Concrete branch results can join at an explicitly present parent aura or `@`. Some known tuple and record positions acquire matching faces; other variable-dependent face merges, general branch tag context and ambiguous call-result propagation remain unsupported; function compatibility involving nested `@` and variable-dependent joins remain unsupported except for equal types and the source-bound gate-sample proof below. For a single recursive gate outside a group, the reporting path repeats inference rather than instantiating its generalized interface inside its own body; a group report uses its stored schemes. This adds work, and the current dependency pass can take quadratic time on long forward chains; the milestone's speed target remains unverified. A separate conservative pass reports unions whose cases are provably disjoint or overlapping and leaves other cases unresolved; it does not claim the mold is checked. Unsupported forms are reported as such, and the partial output says the module has not been checked.
60+
61+Uncontextual `?-` branches share one result join across loobean, unit, list and known-union folds. They first unify the arm types and retain the resulting substitution, including gate-free constraints. If unification fails, they widen only to an explicitly present parent aura or unrestricted `@`; sibling auras do not acquire a guessed common parent. Multi-arm union folds first unify as a group; if that fails, they select an explicitly present atom parent independently of arm order and bind variables to that final parent. Explicit `@` accepts atom singletons and restricted atom variables. Deferred boolean branches try the same join before their pending-literal fallback.
60
62
61A direct unshadowed prelude call can use checked source layouts when a positional argument is a directly named, already inferred root gate. For two-slot function samples, the checker can match a named update against an unnamed generic gate sample without confusing a binder face with a nested record face. Both explicitly named slots must agree; source boundaries are evidence for this fit, not a call-arity rule. The source gate and prelude annotation must be available from their checked bindings. Local or dynamic gates, aliases without direct evidence, recursive or SCC placeholder bodies, other sample shapes and unresolved call-sample variables remain unsupported by this proof. Ordinary inference remains the fallback.
63A direct unshadowed prelude call can use checked source layouts when a positional argument is a directly named, already inferred root gate. For two-slot function samples, the checker can match a named update against an unnamed generic gate sample without confusing a binder face with a nested record face. Both explicitly named slots must agree; source boundaries are evidence for this fit, not a call-arity rule. The source gate and prelude annotation must be available from their checked bindings. Local or dynamic gates, aliases without direct evidence, recursive or SCC placeholder bodies, other sample shapes and unresolved call-sample variables remain unsupported by this proof. Ordinary inference remains the fallback.
62
64
@@ -66,24 +68,28 @@ Before the empty-capital optimization below, single sequential eval runs includi
66
68
67Restricted-number promotion only applies to written capital variables. If none are present, it returns immediately instead of traversing the environment. In one startup-inclusive pair of runs on 2,000 independent gates, output was byte-identical and user CPU fell from 71.67 to 38.26 seconds; wall time was 72.80 versus 51.66 seconds while other checks were running. This does not establish a bound for dependent modules or a complete-checker benchmark.
69Restricted-number promotion only applies to written capital variables. If none are present, it returns immediately instead of traversing the environment. In one startup-inclusive pair of runs on 2,000 independent gates, output was byte-identical and user CPU fell from 71.67 to 38.26 seconds; wall time was 72.80 versus 51.66 seconds while other checks were running. This does not establish a bound for dependent modules or a complete-checker benchmark.
68
70
69−A bounded source proof can also establish distinct literal heads when a union case is a one-hop application of a uniquely resolved local generic mold. It compares literal runtime nouns and checks the original mold normally before publishing an interface. The same source proof improves the partial report, which still says the mold is not checked. The new proof declines nested or qualified applications, opaque references, recursive-index states, holes and deferred obligations; other valid unions can remain unsupported. A 256-node source budget and a separate 256-entry inherited-state budget apply per attempt. They do not bound the existing pairwise union pass, parsing, atom or name sizes, or downstream checking. Prepared interfaces and inference state remain trusted inputs. `tools/type-union-source-test` and the shared ship guard exercise source resolution, reporting, rollback and these bounds. A separate positive witness can identify overlap in two-field, literal-headed cases when a unique one-hop local, one-parameter generic alias is applied to a concrete primitive payload. It compares the literal noun values and proves the payloads have a shared noun, so an empty or unknown payload is not a witness. The partial report identifies both original case sites. `infer-jibb-file-detailed` returns structured overlap evidence for the first failed mold, including the originating path, exact source, mold name and both case spans. Ordinary Jibb imports preserve a child’s evidence through source and cache checks; the legacy `infer-jibb-file` API remains a text-result adapter and renders both excerpts. Specialized API and prepared-prelude paths retain their existing generic or text-only error boundaries. This witness uses a shared 256-node source/pair budget per attempt; generic-wrapper parameter validation has a separate 256-entry cap. An unsupported earlier case may hide a later overlap. Existing pairwise union analysis, parsing, atom and name sizes, source-excerpt rendering, and downstream checking remain outside these budgets. `tools/type-union-alias-overlap-test` checks the source proof and partial report; `tools/type-full-overlap-test` checks the detailed and legacy full-module paths, source attribution and cache behavior.
71+A bounded source proof can also establish distinct literal heads when a union case is a one-hop application of a uniquely resolved local generic mold. It compares literal runtime nouns and checks the original mold normally before publishing an interface. The same source proof improves the partial report, which still says the mold is not checked. The new proof declines nested or qualified applications, opaque references, recursive-index states, holes and deferred obligations; other valid unions can remain unsupported. A 256-node source budget and a separate 256-entry inherited-state budget apply per attempt. They do not bound the existing pairwise union pass, parsing, atom or name sizes, or downstream checking. Prepared interfaces and inference state remain trusted inputs. The `tests/lib/jibb-union-source.hoon` suite exercises source resolution, reporting, rollback and these bounds under eval (`tools/test-arms jibb-union-source`) and on the ship. A separate positive witness can identify overlap in two-field, literal-headed cases when a unique one-hop local, one-parameter generic alias is applied to a concrete primitive payload. It compares the literal noun values and proves the payloads have a shared noun, so an empty or unknown payload is not a witness. The partial report identifies both original case sites. The partial report and the full module check find overlaps with one helper, `mold-overlap-witness`: it takes the first overlapping pair from the pairwise projection, which covers atoms, `?` and literal constants, and nested literal-headed cells, and tries this source witness only when no pair overlaps and some pair stays unknown. A projected overlap is therefore named even when the source witness would prove an earlier pair. For the same union both paths name the same pair, but the full check attaches evidence only when that union is the first mold whose inference fails and its generic parameters are valid; an earlier failing mold, including one that refers to the union, and a union with duplicate or too many parameters keep the generic error. `infer-jibb-file-detailed` returns structured overlap evidence for the first failed mold, including the originating path, exact source, mold name and both case spans. Ordinary Jibb imports preserve a child’s evidence through source and cache checks; the legacy `infer-jibb-file` API remains a text-result adapter and renders both excerpts. Specialized API and prepared-prelude paths retain their existing generic or text-only error boundaries. This witness uses a shared 256-node source/pair budget per attempt; generic-wrapper parameter validation has a separate 256-entry cap. An unsupported earlier case may hide a later overlap. The pairwise projection has no budget: the full check runs it before inferring a union's cases, and once more, to find the pair, on a failed union mold whose generic parameters are valid. Parsing, atom and name sizes, source-excerpt rendering, and downstream checking also remain outside these budgets. `tests/lib/jibb-union-alias-overlap.hoon` checks the source proof and partial report; `tests/lib/jibb-full-overlap-basic.hoon` and `tests/lib/jibb-full-overlap-graph.hoon` check the detailed and legacy full-module paths, source attribution and cache behavior.
70
72
71A single-arm cell pattern can bind two or more positions, with its last binder capturing the remaining tail. Duplicate and shadowed names are rejected. A definite non-cell spine fails; an intermediate union or collection that might contain a cell remains unsupported. For a known non-union cell, a separate one-arm rule also accepts structured patterns, including nested literal and wildcard positions, when the existing coverage proof establishes the whole pattern. It binds payloads with their original types and checks result context; unknown, partially covered, union or recursive spines stay unsupported.
73A single-arm cell pattern can bind two or more positions, with its last binder capturing the remaining tail. Duplicate and shadowed names are rejected. A definite non-cell spine fails; an intermediate union or collection that might contain a cell remains unsupported. For a known non-union cell, a separate one-arm rule also accepts structured patterns, including nested literal and wildcard positions, when the existing coverage proof establishes the whole pattern. It binds payloads with their original types and checks result context; unknown, partially covered, union or recursive spines stay unsupported.
72
74
73String 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.
75String 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.
74
76
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+
75The 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.
79The 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.
76
80
77The 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.
81The 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.
78
82
79A 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.
83A 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.
80
84
81−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.
82
86
83Nested 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.
87Nested 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.
84
88
85For 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.
89For 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.
86
90
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+
87Multi-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.
93Multi-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.
88
94
89A 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.
95A 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.
@@ -98,9 +104,11 @@ The checked inference fragment represents the empty mold `!!` explicitly. A cell
98
104
99A 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.
105A 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.
100
106
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+
101A 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.
109A 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.
102
110
103−The 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; `tools/importer-test` compares the internal projection under eval, and the ship test compares the same golden output. `tools/type-import-test` and `tools/type-mark-test` compare bridge reports under eval and on the ship. `tools/type-tlon-test` and its ship counterpart exercise four real Tlon presence unions and a field read through the source-aware reader and partial checker. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
111+The 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.
104
112
105An import-free Jibb library can export an opaque single-parameter recursive identity when its source has exactly two distinct term-tagged cases: a text leaf and a node containing `(list (name M))`, optionally with one `$-(@t M)` event field. A module-local index records the exact parsed source, defining path and prepared prelude interface; it is shared across that module's inference passes, and its canonical `list` must be source-backed. The normal resolver publishes an interface only after all ordinary mold and value checks succeed. Same-origin aliases retain the defining identity and independently instantiate type arguments; distinct origins remain unsupported. The opaque identity is conservatively treated as gate-bearing for numeric defaulting, and gate-freedom remains unknown. Explicit literal-headed construction uses a source-proven one-layer view: the event result receives the existing type argument and recursive children keep the defining identity. It consumes the existing shared 256-step recursive inference budget, and a per-view 4,096-visit guard bounds the new face and substitution scan; longer scans decline. These bounds do not cover parsing, existing inference, atom sizes or repeated attempts. One startup-inclusive, shared-load comparison of 100 valid and 100 invalid source definitions took 29.67 s wall / 25.14 s user CPU before this slice and 33.47 s / 26.99 s with it; the former declined all 200 while the latter inferred the valid definitions. These single runs are not a production benchmark. Matches over explicit source tags, flat binder or wildcard fields, and nonbinding catch-alls use that same one-layer view and existing binder, coverage and branch checks. Up to 128 arms are screened per attempt; longer matches decline. A single-arm match on a direct in-scope wing can report its missing case, and a contextual one-arm call subject can use a nonbinding catch-all. Recursive children retain their nominal type and arguments. Subject recognition and view validation can each scan substitutions, and the scan cap applies separately to each attempt. In one separate startup-inclusive comparison of 100 valid and 100 invalid source matches, the construction-only checker took 30.18 s wall / 29.31 s user CPU and declined all 200, while the pattern slice took 28.28 s / 27.69 s and inferred or diagnosed them. These single shared-load figures are not production benchmarks. General structural fits, whole-case binders, nested recursive patterns, uncontextualized single-arm call subjects, recursive source with imports and local recursive molds remain unsupported; the test tree does not prescribe the eventual `element` representation. Caller-supplied detached interfaces and caches retain the existing trusted-input contract.
113An import-free Jibb library can export an opaque single-parameter recursive identity when its source has exactly two distinct term-tagged cases: a text leaf and a node containing `(list (name M))`, optionally with one `$-(@t M)` event field. A module-local index records the exact parsed source, defining path and prepared prelude interface; it is shared across that module's inference passes, and its canonical `list` must be source-backed. The normal resolver publishes an interface only after all ordinary mold and value checks succeed. Same-origin aliases retain the defining identity and independently instantiate type arguments; distinct origins remain unsupported. The opaque identity is conservatively treated as gate-bearing for numeric defaulting, and gate-freedom remains unknown. Explicit literal-headed construction uses a source-proven one-layer view: the event result receives the existing type argument and recursive children keep the defining identity. It consumes the existing shared 256-step recursive inference budget, and a per-view 4,096-visit guard bounds the new face and substitution scan; longer scans decline. These bounds do not cover parsing, existing inference, atom sizes or repeated attempts. One startup-inclusive, shared-load comparison of 100 valid and 100 invalid source definitions took 29.67 s wall / 25.14 s user CPU before this slice and 33.47 s / 26.99 s with it; the former declined all 200 while the latter inferred the valid definitions. These single runs are not a production benchmark. Matches over explicit source tags, flat binder or wildcard fields, and nonbinding catch-alls use that same one-layer view and existing binder, coverage and branch checks. Up to 128 arms are screened per attempt; longer matches decline. A single-arm match on a direct in-scope wing can report its missing case, and a contextual one-arm call subject can use a nonbinding catch-all. Recursive children retain their nominal type and arguments. Subject recognition and view validation can each scan substitutions, and the scan cap applies separately to each attempt. In one separate startup-inclusive comparison of 100 valid and 100 invalid source matches, the construction-only checker took 30.18 s wall / 29.31 s user CPU and declined all 200, while the pattern slice took 28.28 s / 27.69 s and inferred or diagnosed them. These single shared-load figures are not production benchmarks. General structural fits, whole-case binders, nested recursive patterns, uncontextualized single-arm call subjects, recursive source with imports and local recursive molds remain unsupported; the test tree does not prescribe the eventual `element` representation. Caller-supplied detached interfaces and caches retain the existing trusted-input contract.
106
114
@@ -116,7 +124,7 @@ In single startup-inclusive runs of eight Hoon reads, a benign three-case union
116
124
117The partial report can diagnose certain non-gate value dependency cycles, including cycles through gates. It requires an explicit atom or loobean result cast and a syntactically proven dependency group with unshadowed simple samples; it identifies the value and a dependency site. Untyped results, branches, nested definitions, qualified wings and complex samples remain unsupported. The proof constructs an additional dependency graph. One 24-case recursive/generic eval run took 19.7 s with it and 18.6 s before it, including startup; these single runs do not isolate the graph cost.
125The partial report can diagnose certain non-gate value dependency cycles, including cycles through gates. It requires an explicit atom or loobean result cast and a syntactically proven dependency group with unshadowed simple samples; it identifies the value and a dependency site. Untyped results, branches, nested definitions, qualified wings and complex samples remain unsupported. The proof constructs an additional dependency graph. One 24-case recursive/generic eval run took 19.7 s with it and 18.6 s before it, including startup; these single runs do not isolate the graph cost.
118
126
119−The source-backed `+api-path-analysis-source` is a separate partial analysis, not an API check: it resolves reachable Jibb imports and declared mark graphs and returns path and scry segments, full and diff mark identities and their types. It also checks derived-name collisions. Full and diff payloads must be direct declared mark names; typed scry parameters must be a same-name, same-aura subset of the watch parameters, and unknown or duplicate segment binders fail closed. It creates no request gates. The caller must pass a trusted prepared prelude and unchanged source-aware reader results.
127+The source-backed `+api-path-analysis-source` is a separate partial analysis, not an API check: it resolves reachable Jibb imports and declared mark graphs and returns path and scry segments, full and diff mark identities and their types. It also checks derived-name collisions and reports a clash as a definite error at both sites. Full and diff payloads must be direct declared mark names; typed scry parameters must be a same-name, same-aura subset of the watch parameters, and unknown or duplicate segment binders fail closed. It creates no request gates. The caller must pass a trusted prepared prelude and unchanged source-aware reader results.
120
128
121`+api-path-evidence-source` retains that analysis with the API source, complete prepared prelude (including reserved names), supplied reader results and resolved Jibb dependency cache. `+api-path-watchability` classifies a unique declaration as watchable or not watchable, or reports unknown when evidence is absent or ambiguous. The artifact and reader results are trusted host inputs; the host must bind them to the source versions used later. This is declaration evidence, not proof about an arbitrary request value, a checked API module, a runtime validator or an island watch.
129`+api-path-evidence-source` retains that analysis with the API source, complete prepared prelude (including reserved names), supplied reader results and resolved Jibb dependency cache. `+api-path-watchability` classifies a unique declaration as watchable or not watchable, or reports unknown when evidence is absent or ambiguous. The artifact and reader results are trusted host inputs; the host must bind them to the source versions used later. This is declaration evidence, not proof about an arbitrary request value, a checked API module, a runtime validator or an island watch.
122
130
@@ -124,7 +132,7 @@ For a unique supported declaration, `+api-request-parts` retains that evidence w
124
132
125`+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.
133`+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.
126
134
127−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. 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.
128
136
129A 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.
137A 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.
130
138
@@ -140,27 +148,27 @@ The same post-inference, post-request-graph kind boundary accepts a static `main
140
148
141A store `main` is recognized only as a direct, unqualified `(store init update)` call with two simple wing arguments, modulo grouping, independently of its directory. Its module must declare exactly one ordinary `state` mold and one ordinary, nongeneric local `+$ poke` action mold. Both remain in ordinary mold/value inference and are exported. `+store-main-closed` checks the canonical closed store main, exact init/state equality, and an invariant `$-([action state] state)` update after erasing only the two outer binder faces. It deliberately performs no gate-free-state check. The direct form can recover a missing main from checked components; aliases and hand-built records cannot.
149A store `main` is recognized only as a direct, unqualified `(store init update)` call with two simple wing arguments, modulo grouping, independently of its directory. Its module must declare exactly one ordinary `state` mold and one ordinary, nongeneric local `+$ poke` action mold. Both remain in ordinary mold/value inference and are exported. `+store-main-closed` checks the canonical closed store main, exact init/state equality, and an invariant `$-([action state] state)` update after erasing only the two outer binder faces. It deliberately performs no gate-free-state check. The direct form can recover a missing main from checked components; aliases and hand-built records cannot.
142
150
143−The store interface adds a derived `$-([action $-((unit @t) M)] (cmd M))` poke helper and a generic `$-($-(state M) (ask M))` state request after validating the exact internal `raw-poke`, canonical `cmd`, standard `unit` and `ask` representations. Derived names must not collide with values, imports or other derived names. Store request certificates are distinct from API certificates and retain the exact store path, source, state and action identities across graph merges. `+derived-store-request-member` requires the selected interface's unique state member and action constructor to match freshly derived canonical schemes and the same certificate to occur in both interface and consumer graphs. Store state is watchable by definition only after those checks; page loads continue to accept API evidence alone. Multi-action declarations, lowering and execution are outside this slice.
151+The store interface adds a derived `$-([action $-((unit @t) M)] (cmd M))` poke helper and a generic `$-($-(state M) (ask M))` state request after validating the exact internal `raw-poke`, canonical `cmd`, standard `unit` and `ask` representations. Derived names must not collide with values, imports or other derived names. Once the store's `state` and `poke` molds are unique and nongeneric and `main`'s `store` is the prelude's builder, such a collision is a definite error, reported before other scope conflicts, showing the mold the name derives from and the clashing definition or import face. Store request certificates are distinct from API certificates and retain the exact store path, source, state and action identities across graph merges. `+derived-store-request-member` requires the selected interface's unique state member and action constructor to match freshly derived canonical schemes and the same certificate to occur in both interface and consumer graphs. Store state is watchable by definition only after those checks; page loads continue to accept API evidence alone. Multi-action declarations, lowering and execution are outside this slice.
144
152
145−When only that program's initializer and `main` are unresolved, a bounded transactional retry can derive the initializer's expected gate from the resolved update, view and subscription components. It instantiates all schemes above the greatest variable ID in the module and prelude, reuses the source-backed positional fit and stable replay, and leaves only the initializer's data variable open. The named initializer must be a direct gate whose transparent body is a tuple ending in null. Its own sample fixes data; ordinary inference, product and whole-gate fits, pending-tag and finalization checks, and a fresh ordinary `main` inference must all succeed before the ordinary kind and graph checks publish anything. Aliases, non-main libraries, simultaneous unresolved subscriptions, nonempty subscriptions and unrelated pending tags decline.
153+When only that program's initializer and `main` are unresolved, one transactional retry checks the initializer, which must be a direct gate with a closed, tag-free written sample, against the program's closed model. Update's written two-item sample gives the model when it can be read. Otherwise main's own source-backed program fit gives it: update, view and subs are instantiated above the greatest variable ID in the module and prelude and fitted together against the prelude `program` sample, with the initializer an open variable. Only the initializer's data may stay open, a replay of the fit must not change the substitution, and the model must come out closed and tag-free. So an update written `|= =input`, `|= in=input` or generic in its model, and a view and subs with generic samples, still let the initializer check. The body is inferred with the model as context; a body that context inference cannot take, such as a branch over a nested call's union, is inferred ordinarily as a whole gate instead, and its sample must fit the written one. The product and whole-gate fits, pending-tag and finalization checks, and a fresh ordinary `main` inference must all succeed before the ordinary kind and graph checks publish anything. This one path replaced a separate retry for bodies ending in null and a gate that took only a null sample (review question 8), so any body and any closed sample of a direct gate check the same way. The fresh `main` inference is what checks that the four components agree: an initializer that fits update's model while view uses another message passes recovery, and `main` then rejects the program. Aliased mains or initializers, non-main libraries, simultaneously unresolved subscriptions and unrelated pending tags decline.
146
154
147−Ordinary inference runs for every component before recovery, so a keyed view no longer causes an already-valid initializer to be skipped. Recovery is a fallback for unresolved components, not a replacement for definitions that check normally. The regression uses a call-bodied annotated initializer, which is outside the tuple-bodied initializer recovery shape.
155+Ordinary inference runs for every component before recovery, so a keyed view no longer causes an already-valid initializer to be skipped. Recovery is a fallback for unresolved components, not a replacement for definitions that check normally. The regression's initializer is a gate under a `^-` cast to its full type. Ordinary inference checks it, but recovery, which takes only a direct gate, cannot, so the fixture fails if a keyed view ever skips ordinary inference again.
148
156
149−A component-local recovery sequence handles a recognized direct program whose context-dependent definitions cannot resolve ordinarily. Update first derives its result from its inferred two-slot sample and canonical `cmd`/`list` templates. Subscription recovery then checks the same message/model relation and the canonical fourth slot. A narrow keyed-view proof finds exactly one direct `each (turn xs mapper)` site, derives the mapper from the actual `each` and `turn` schemes, and recovers the view before the existing initializer and ordinary `main` retries. Every recovered scheme must be closed and freshly allocated above the current environment and prelude IDs. Non-gate views and aliases decline without crashing. Final publication still requires all module definitions, the program-mold and gate-free checks, and request-value watchability.
157+A component-local recovery sequence handles a recognized direct program whose context-dependent definitions cannot resolve ordinarily. Update first derives its result from its inferred two-slot sample and canonical `cmd`/`list` templates. Subscription recovery then checks the same message/model relation and the canonical fourth slot. A narrow keyed-view proof finds exactly one direct `each (turn xs mapper)` site, derives the mapper from the actual `each` and `turn` schemes, and recovers the view before the existing initializer and ordinary `main` retries. Every recovered scheme must be closed and freshly allocated above the current environment and prelude IDs. That bound comes from one unbudgeted pass over the environment and prelude schemes, which treats named recursive types as leaves and declines only when a scheme still holds an unresolved literal tag. Non-gate views and aliases decline without crashing. Final publication still requires all module definitions, the program-mold and gate-free checks, and request-value watchability.
150
158
151−Canonical `element` composition has two tightly scoped accommodations. Recursive result context is allowed only when every recursive side has the prepared prelude's `element` origin. When ordinary list-item fitting fails, an `element` target may instead prove its message argument invariantly or select one exact literal case with a full payload fit; a successful ordinary fit always takes precedence. This covers the unchanged todo's union controls and raw constructors without opening those paths to other unions. `tools/type-todo-full-test` checks the byte-identical island through both full APIs, the exact closed `main` type, structural downstream import, and model/message/mapper/watch rejection controls. It does not execute Jibb or implement runtime watching.
159+Canonical `element` composition has two tightly scoped accommodations. Recursive result context is allowed only when every recursive side has the prepared prelude's `element` origin. When ordinary list-item fitting fails, an `element` target may instead prove its message argument invariantly or select one exact literal case with a full payload fit; a successful ordinary fit always takes precedence. This covers the unchanged todo's union controls and raw constructors without opening those paths to other unions. The `tests/lib/jibb-todo-full.hoon` suite checks the byte-identical island through both full APIs, the exact closed `main` type, structural downstream import, and model/message/mapper/watch rejection controls. It does not execute Jibb or implement runtime watching.
152
160
153Each case's canonical API identity and source-derived schema travel across imports in a nonrecursive graph certificate containing the exact source bundle, prelude, reserved scope and trusted reader results. Cached interfaces must match those inputs and cannot hide an active ancestor; unknown legacy entries are rebuilt from their unique supplied source. Request-bearing closures are limited to 256 paths and requests. Closed gate samples can also fit when an unnamed input slot corresponds to a named one, provided products are identical and nested value faces and ambiguous cell tails remain intact. This is type inference only: request lowering, runtime schema validation and value watchability proofs are not implemented.
161Each case's canonical API identity and source-derived schema travel across imports in a nonrecursive graph certificate containing the exact source bundle, prelude, reserved scope and trusted reader results. Cached interfaces must match those inputs and cannot hide an active ancestor; unknown legacy entries are rebuilt from their unique supplied source. Request-bearing closures are limited to 256 paths and requests. Closed gate samples can also fit when an unnamed input slot corresponds to a named one, provided products are identical and nested value faces and ambiguous cell tails remain intact. This is type inference only: request lowering, runtime schema validation and value watchability proofs are not implemented.
154
162
155`+golden-types-with-prelude` accepts case-local Jibb module sources alongside `/sur` and mark results and the vendored prelude source. It resolves reachable ordinary library modules in dependency order, caching completed interfaces per invocation and exporting supported closed value schemes, direct generic unions, and simple or nonrecursive generic mold aliases whose bodies the fragment supports. It detects missing sources and cycles and rejects a dependency if its interface cannot be inferred by the fragment. Qualified wings can also read nested fields of an imported value, instantiating that value’s scheme independently at each use; missing, ambiguous and non-record fields remain unsupported.
163`+golden-types-with-prelude` accepts case-local Jibb module sources alongside `/sur` and mark results and the vendored prelude source. It resolves reachable ordinary library modules in dependency order, caching completed interfaces per invocation and exporting supported closed value schemes, direct generic unions, and simple or nonrecursive generic mold aliases whose bodies the fragment supports. It detects missing sources and cycles and rejects a dependency if its interface cannot be inferred by the fragment. Qualified wings can also read nested fields of an imported value, instantiating that value’s scheme independently at each use; missing, ambiguous and non-record fields remain unsupported.
156
164
157−The supplied prelude is parsed into a **partial interface**: all names actually declared in the source are reserved, while only the molds and values this fragment can infer are available. These include the validated standard `list` mold, `unit`, the doc-exact generic `cmd` union, `same`, `fall`, `need`, `bond`, `lure`, `weld`, `snoc`, `turn`, `lent`, `zing`, `flop`, `rear`, `drop`, `skim`, `skip`, `murn`, `join`, `snip`, `levy`, `lien`, `cork`, `corl`, `cury`, `curr`, `lead`, `late`, `trip` and `tuba`; unsupported entries remain unavailable. The validated `list` is injected while the prelude’s gates are inferred; `weld` and `turn` use ordinary explicit result casts. An absent or altered `list` is not injected, and an altered declaration cannot leak through a direct or transitive mold alias. The same validated template is available when prelude mold aliases are prepared, so supported direct and transitive aliases can use it. A named prelude union keeps the fixed `/lib/jibb/prelude/jibb` origin in every module, and its name remains unqualified when a library exports a type containing it. The prelude inventory is incomplete, so reserving the names in this source does not establish complete shadowing coverage. The source-backed internal prelude defines `poke`, which the public prelude re-exports as an ordinary transparent type. A dedicated trusted internal-prelude preparation path also supplies private comparison, arithmetic and text-conversion schemes for the Jibb-written `gth`, `add`, `dec`, `trip` and `tuba` wrappers. Ordinary module resolution rejects that primitive path even if a caller supplies a spoofed root or bundle. The low-level prepared interface is still trusted host input; the host must select the vendored sources and canonicalize paths. Primitive execution and shape-based jet recognition are not implemented. The Jibb-written `lth`, `gte` and `lte` gates compose the source-backed `gth` and `not` gates; supported calls infer a shared atom constraint and return `?`. Their execution and jet recognition await the backend. The source-backed `add` and `dec` wrappers use private arithmetic interfaces whose shared atom variable excludes loobeans; the partial checker preserves that constraint through supported inference and prints `where A is an atom other than ?`. The partial checker resolves the supported `poke` source shape, preserves its public name, and rejects ordinary imports of the private internal path. The Jibb-written `lent` recursively counts a list using `add`; the partial checker infers its generic list argument and `@ud` result. Its execution and jet recognition remain unverified until the backend exists. The Jibb-written `zing` concatenates homogeneous lists in order using `weld`; the checker infers `(list (list A))` to `(list A)`, including for gate elements. Hoon `zing` also accepts heterogeneous noun lists, which this type does not express. `tools/hoon --raw -f tools/testdata/zing-hoon-reference.hoon` compares an equivalent Hoon recursion with Hoon `zing` on selected finite inputs; it does not execute Jibb or verify lowering or jet recognition. The Jibb-written `lead` and `late` are curried pair constructors: `((lead a) b)` returns `[a b]`, while `((late a) b)` returns `[b a]`. The checker infers independent argument types and accepts gates as ordinary values; neither helper invokes an input gate. A Hoon translation is compared with Hoon’s helpers by `tools/hoon --raw -f tools/testdata/lead-late-hoon-reference.hoon`. This does not execute Jibb or verify lowering or jet recognition. An imported API with one mark and a matching direct `+$ poke` declaration can export a derived constructor and retain agent/mark metadata when the source representation has the supported agent case. Other API shapes, complete private module checking, root API and kind checking, stores, complete `ask` and `pure` checking, lowering and runtime effects remain unfinished. A possible store or root API declaring `+$ poke` reports that kind or scope needs unsupported inference; definite duplicate declarations and unrelated shadowing still report conflicts. Prepared interfaces and caches are trusted caller inputs; the future host and linker must ensure the private source validated during preparation is the same version used to lower derived constructors. A `*` payload may contain gates, so the fragment treats it conservatively; full gate-free checks are unfinished. The shared 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.
165+The supplied prelude is parsed into a **partial interface**: all names actually declared in the source are reserved, while only the molds and values this fragment can infer are available. These include the validated standard `list` mold, `unit`, the doc-exact generic `cmd` union, `same`, `fall`, `need`, `bond`, `lure`, `weld`, `snoc`, `turn`, `lent`, `zing`, `flop`, `rear`, `drop`, `skim`, `skip`, `murn`, `join`, `snip`, `levy`, `lien`, `cork`, `corl`, `cury`, `curr`, `lead`, `late`, `trip` and `tuba`; unsupported entries remain unavailable. The validated `list` is injected while the prelude’s gates are inferred; `weld` and `turn` use ordinary explicit result casts. An absent or altered `list` is not injected, and an altered declaration cannot leak through a direct or transitive mold alias. The same validated template is available when prelude mold aliases are prepared, so supported direct and transitive aliases can use it. A named prelude union keeps the fixed `/lib/jibb/prelude/jibb` origin in every module, and its name remains unqualified when a library exports a type containing it. The prelude inventory is incomplete, so reserving the names in this source does not establish complete shadowing coverage. The source-backed internal prelude defines `poke`, which the public prelude re-exports as an ordinary transparent type. A dedicated trusted internal-prelude preparation path also supplies private comparison, arithmetic and text-conversion schemes for the Jibb-written `gth`, `add`, `dec`, `trip` and `tuba` wrappers. Ordinary module resolution rejects that primitive path even if a caller supplies a spoofed root or bundle. The low-level prepared interface is still trusted host input; the host must select the vendored sources and canonicalize paths. Primitive execution and shape-based jet recognition are not implemented. The Jibb-written `lth`, `gte` and `lte` gates compose the source-backed `gth` and `not` gates; supported calls infer a shared atom constraint and return `?`. Their execution and jet recognition await the backend. The source-backed `add` and `dec` wrappers use private arithmetic interfaces whose shared atom variable excludes loobeans; the partial checker preserves that constraint through supported inference and prints `where A is an atom other than ?`. The partial checker resolves the supported `poke` source shape, preserves its public name, and rejects ordinary imports of the private internal path. The Jibb-written `lent` recursively counts a list using `add`; the partial checker infers its generic list argument and `@ud` result. Its execution and jet recognition remain unverified until the backend exists. The Jibb-written `zing` concatenates homogeneous lists in order using `weld`; the checker infers `(list (list A))` to `(list A)`, including for gate elements. Hoon `zing` also accepts heterogeneous noun lists, which this type does not express. The `test-zing-reference` arm of `tests/lib/jibb-hoon-reference.hoon` compares an equivalent Hoon recursion with Hoon `zing` on selected finite inputs; it does not execute Jibb or verify lowering or jet recognition. The Jibb-written `lead` and `late` are curried pair constructors: `((lead a) b)` returns `[a b]`, while `((late a) b)` returns `[b a]`. The checker infers independent argument types and accepts gates as ordinary values; neither helper invokes an input gate. A Hoon translation is compared with Hoon’s helpers by the same suite's `test-lead-late-reference` arm. This does not execute Jibb or verify lowering or jet recognition. An imported API with one mark and a matching direct `+$ poke` declaration can export a derived constructor and retain agent/mark metadata when the source representation has the supported agent case. Other API shapes, complete private module checking, root API and kind checking, stores, complete `ask` and `pure` checking, lowering and runtime effects remain unfinished. A possible store or root API declaring `+$ poke` reports that kind or scope needs unsupported inference; definite duplicate declarations and unrelated shadowing still report conflicts. Prepared interfaces and caches are trusted caller inputs; the future host and linker must ensure the private source validated during preparation is the same version used to lower derived constructors. A `*` payload may contain gates, so the fragment treats it conservatively; full gate-free checks are unfinished. The shared 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.
158
166
159`+prepare-prelude` derives the interface and declared-name inventory from the trusted vendored source. Hosts can reuse its result with `+golden-types-with-prepared-prelude`; they must pass the unchanged result of preparation, not an independently constructed value. Empty, malformed and duplicate-name prelude sources fail closed. The source-taking `+prepare-prelude` and `+golden-types-with-prelude` do not supply the internal module; their `-and-internal` or `-with-internal` variants accept its source for the supported private import. API files, modules with `main`, unsupported definitions and many other features remain outside this subset. The older `+golden-types-with-modules` entry point fails closed for imports because it has no prelude scope. None of these partial reports claims the module has been checked.
167`+prepare-prelude` derives the interface and declared-name inventory from the trusted vendored source. Hosts can reuse its result with `+golden-types-with-prepared-prelude`; they must pass the unchanged result of preparation, not an independently constructed value. Empty, malformed and duplicate-name prelude sources fail closed. The source-taking `+prepare-prelude` and `+golden-types-with-prelude` do not supply the internal module; their `-and-internal` or `-with-internal` variants accept its source for the supported private import. API files, modules with `main`, unsupported definitions and many other features remain outside this subset. The older `+golden-types-with-modules` entry point fails closed for imports because it has no prelude scope. None of these partial reports claims the module has been checked.
160
168
161The prepared interface includes the source-backed UI molds and constructors, the full nonrecursive `element` union, and the exact `program` and `page` records and builders. Its element union erases nested child, keyed-item and table payloads to `*`, while public constructor schemes retain typed composition and independent key parameters. `types-prelude-ui` checks those schemes and selected valid and invalid compositions. A child-message mismatch currently fails closed as an unsupported list-item constraint rather than a definite mismatch diagnostic. Raw-constructor encapsulation, duplicate-attribute checks, rendering, navigation, storage and execution remain outside this slice.
169The prepared interface includes the source-backed UI molds and constructors, the full nonrecursive `element` union, and the exact `program` and `page` records and builders. Its element union erases nested child, keyed-item and table payloads to `*`, while public constructor schemes retain typed composition and independent key parameters. `types-prelude-ui` checks those schemes and selected valid and invalid compositions. A child-message mismatch currently fails closed as an unsupported list-item constraint rather than a definite mismatch diagnostic. Raw-constructor encapsulation, duplicate-attribute checks, rendering, navigation, storage and execution remain outside this slice.
162
170
163−The Grammar's buttons example has a shared full-check fixture. Without `add-button`, `labelled` and `wide` export their exact generic `(element A)` and `(list attr)` schemes through detailed and legacy inference. The ordinary call fit handles this by unifying a variable actual argument with the body of an expected faced slot, rather than putting the sample face on the argument's type. With the unchanged `add-button`, final incompleteness triggers a diagnostic-only retry bounded to 64 missing definitions. A pending tag retains its literal span, so the error says that nothing fixes the union of `%add` at the literal and includes its source excerpt. Other incomplete modules keep the generic error, and successful modules never run the retry. This checks types only; it does not render or execute buttons.
171+The Grammar's buttons example has a shared full-check fixture. Without `add-button`, `labelled` and `wide` export their exact generic `(element A)` and `(list attr)` schemes through detailed and legacy inference. The ordinary call fit handles this by unifying a variable actual argument with the body of an expected faced slot, rather than putting the sample face on the argument's type. With the unchanged `add-button`, final incompleteness triggers a diagnostic-only retry bounded to 64 missing definitions. A pending tag retains its literal span, so the error says that nothing fixes the union of `%add` at the literal and includes its source excerpt. Otherwise, when a missing value is a gate whose own sample has the name of a top-level value, import face or prelude value, the error is that the sample shadows a name, shown at the sample: with `++ user |= x=@t (helper x)` and `++ helper |= user=@t user`, it is `helper`'s sample `user`. Other incomplete modules keep the generic error, which names one missing value: the first whose module dependencies all resolved. When every missing value waits on another, it follows the first value each waits on, from the first missing value, until a value repeats, and names that value. The walk is over the syntactic dependency graph, which ignores binders: a local binder with a top-level value's name, such as a cell-sample item or a nested gate's sample, reads as a dependency on that value. The named value lies on a cycle of that graph but may only call into the value that failed; with `++ helper |= x=@t |= user=@t user` instead, it names `user`, and the shadowing is not reported. Successful modules never run the retry. This checks types only; it does not render or execute buttons.
164
172
165The prepared interface also includes the exact documented `theme` mold. Full checking covers the unchanged real `/ui/theme.jibb`, its exact exported record and a structural downstream import, with dark absent/present and field/type rejection controls. The documented present dark record uses explicit backtick unit syntax, as the Decisions tab records; there is no theme-specific inference exception. This is type checking only: contrast validation, theme rendering and routing remain unimplemented.
173The prepared interface also includes the exact documented `theme` mold. Full checking covers the unchanged real `/ui/theme.jibb`, its exact exported record and a structural downstream import, with dark absent/present and field/type rejection controls. The documented present dark record uses explicit backtick unit syntax, as the Decisions tab records; there is no theme-specific inference exception. This is type checking only: contrast validation, theme rendering and routing remain unimplemented.
166
174
@@ -179,7 +187,9 @@ The internal prelude defines transparent `(ask M)` cases for pure, agent and sto
179
187
180Public 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.
188Public 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.
181
189
182−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.
183
193
184## The tree
194## The tree
185
195
@@ -216,15 +226,15 @@ Note 4 has examples of each.
216
226
217## Speed
227## Speed
218
228
219−Starting `urbit eval` and building the library takes about 8 s. A 2,000-line module of 400 definitions then parses in about a second. Loops over definitions, arms, lines and items are tail calls, so a long module grows no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (note 3).
229+Starting `urbit eval` and building the library takes about 27 s, or 24 s without `!:` (`tools/hoon --no-debug`), measured on 2026-11-02. Every timing in this document was measured with `!:`, which the dev tools add so errors have positions, and which makes checker work 2.2 to 2.6 times slower than on a ship; the comparisons hold, but the absolute figures overstate a ship's time. A 2,000-line module of 400 definitions then parses in about a second. Loops over definitions, arms, lines and items are tail calls, so a long module grows no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (note 3).
220
230
221−The experimental deferred constructor path can close a small import-free library transaction when ordinary resolution stalls. It retries definitions whose earlier attempts failed from their original states, retaining only successful attempts. A transaction with at most 64 definitions makes at most 4,096 attempts; it stops after a pass with no progress. This bounds the new attempt count, not each attempt's parsing, type walks or ordinary inference. Deferred definitions are restricted to simple one-component wings, literals, static strings, gates, transparent groups and empty bodies, calls, casts and a restricted boolean branch. Each successful call or cast fit must have exactly equal normalized operands so later substitutions cannot invalidate a face check. A multi-argument call also needs closed argument, sample and product types because positional face checks depend on slot boundaries and whether the result can be a cell. Other fits fail closed. A 512-node screen bounds visited expression nodes and a separate 512-node scan bounds each stability check; neither bounds mold shapes, string-piece checks, parsing, normalization, lookup, or total repeated inference. It accepts only a direct constructor callback with a closed input, records its pending fit under the source-owned inference state, and generalizes each definition against the live environment and pending constraints. Before publication it discharges and replays every edge, rejects unresolved tags or changed replay state, and checks that all molds and values are complete. The reporter reads the committed schemes for definitions added by the transaction. API and store paths, `main`, prepared-prelude recovery, imports, recursive groups, unresolved holes or written capitals, and new projection actions remain outside this full-module path. `%grec` in the constraint or freshness scan is conservatively unsupported. This is not an island-kind, runtime, or watchability check.
231+The experimental deferred constructor path can close a small import-free library transaction when ordinary resolution stalls. It retries definitions whose earlier attempts failed from their original states, retaining only successful attempts. A transaction with at most 64 definitions makes at most 4,096 attempts; it stops after a pass with no progress. This bounds the new attempt count, not each attempt's parsing, type walks or ordinary inference. Deferred definitions are restricted to simple one-component wings, literals, static strings, gates, transparent groups and empty bodies, calls, casts and a restricted boolean branch. Each successful call or cast fit must have exactly equal normalized operands so later substitutions cannot invalidate a face check. A multi-argument call also needs closed argument, sample and product types because positional face checks depend on slot boundaries and whether the result can be a cell. Other fits fail closed. A 512-node screen bounds visited expression nodes and a separate 512-node scan bounds each stability check; neither bounds mold shapes, string-piece checks, parsing, normalization, lookup, or total repeated inference. It accepts only a direct constructor callback with a closed input, records its pending fit under the source-owned inference state, and generalizes each definition against the live environment and pending constraints. Before publication it discharges and replays every edge, rejects unresolved tags or changed replay state, and checks that all molds and values are complete. The reporter reads the committed schemes for definitions added by the transaction. API and store paths, `main`, prepared-prelude recovery, imports, recursive groups, unresolved holes or written capitals, and new projection actions remain outside this full-module path. `%grec` in the constraint scan is conservatively unsupported. This is not an island-kind, runtime, or watchability check.
222
232
223An expected cell type can supply context to both arms of a loobean branch. This slice first retains any ordinary inference that already fits. Otherwise it retries from the original state only when a syntax screen excludes nested branches, casts, gates and local bodies, and a substitution screen excludes structural bindings. Both arms must fit, their normalized results and the expected type must be closed, their result types must match, and both fits must replay without changing the final substitution or fresh-ID counter. A successful retry retains the original arm type and its written faces; a failed retry returns the original inference result. The source and substitution screens each visit at most 512 entries. This permits at most one extra attempt for an eligible branch; the screens do not bound preexisting inference, type walks, list construction, or work across separate analyses.
233An expected cell type can supply context to both arms of a loobean branch. This slice first retains any ordinary inference that already fits. Otherwise it retries from the original state only when a syntax screen excludes nested branches, casts, gates and local bodies, and a substitution screen excludes structural bindings. Both arms must fit, their normalized results and the expected type must be closed, their result types must match, and both fits must replay without changing the final substitution or fresh-ID counter. A successful retry retains the original arm type and its written faces; a failed retry returns the original inference result. The source and substitution screens each visit at most 512 entries. This permits at most one extra attempt for an eligible branch; the screens do not bound preexisting inference, type walks, list construction, or work across separate analyses.
224
234
225In an isolated diagnostic with the real todo API and reader inputs, this cell context allowed the original update body to infer when its result type was written explicitly and experimental source-defined text helpers were supplied. The unchanged island still needs those text helpers, an actual source-backed `program` and UI interface, context propagation across definitions, island-kind checking and watchability proof. This branch change itself provides no runtime implementation or watchability evidence.
235In an isolated diagnostic with the real todo API and reader inputs, this cell context allowed the original update body to infer when its result type was written explicitly and experimental source-defined text helpers were supplied. The unchanged island still needs those text helpers, an actual source-backed `program` and UI interface, context propagation across definitions, island-kind checking and watchability proof. This branch change itself provides no runtime implementation or watchability evidence.
226
236
227−A deferred boolean branch must use both distinct literal loobean patterns. Its subject is unified with `?`; the arms are inferred in source order without contextual retry. Equal normalized arm types are retained directly. When both written arms are direct literals that each created their own unbound pending tag, the checker can instead retain two source-owned fit obligations to a shared, monomorphic result variable. A later definition may close that variable; replay uses the ordinary literal fit, requires a closed atomic target or a union of direct constant/cell cases, and rejects faced targets and faced union cases. It replays all edges under the final substitution without adding bindings or fresh IDs. This does not support deferred list literals, union-pattern reachability, arbitrary branch expressions or prepared-prelude/imported modules. It does not establish request watchability.
237+A deferred boolean branch must use both distinct literal loobean patterns. Its subject is unified with `?`; the arms are inferred in source order without contextual retry. The shared unification-first result join applies before the pending-literal fallback. When both written arms are direct literals that each created their own unbound pending tag, the checker can instead retain two source-owned fit obligations to a shared, monomorphic result variable. A later definition may close that variable; replay uses the ordinary literal fit, requires a closed atomic target or a union of direct constant/cell cases, and rejects faced targets and faced union cases. It replays all edges under the final substitution without adding bindings or fresh IDs. This does not support deferred list literals, union-pattern reachability, arbitrary branch expressions or prepared-prelude/imported modules. It does not establish request watchability.
228
238
229With the caller's unchanged prepared prelude, the partial report can also recover a narrow import-free, non-main ordinary library initializer. A direct tuple literal may retain one source-owned fit obligation for each newly created pending literal until a later exact result cast closes them. A separate bounded candidate screen admits a direct tuple even without a constructor call. The prepared transaction requires exact agreement among the supplied interface, value inventory and reserved molds, and retains the API, store, import and `main` exclusions. It only adds recovered entries to the partial report: the ordinary full-module resolver does not publish them. Wrong unit or draft fields, unrelated pending tags and mold-name collisions fail closed; without the later final cast, the initializer remains not checked. This does not add list-literal deferral or import-aware recovery.
239With the caller's unchanged prepared prelude, the partial report can also recover a narrow import-free, non-main ordinary library initializer. A direct tuple literal may retain one source-owned fit obligation for each newly created pending literal until a later exact result cast closes them. A separate bounded candidate screen admits a direct tuple even without a constructor call. The prepared transaction requires exact agreement among the supplied interface, value inventory and reserved molds, and retains the API, store, import and `main` exclusions. It only adds recovered entries to the partial report: the ordinary full-module resolver does not publish them. Wrong unit or draft fields, unrelated pending tags and mold-name collisions fail closed; without the later final cast, the initializer remains not checked. This does not add list-literal deferral or import-aware recovery.
230
240
docs/development.md+85−66
@@ -6,15 +6,15 @@ How to work on Jibb: the rules the plan sets, how to set up a machine, and what
6
6
7From the plan's Setup and ground rules, and from @iko:
7From the plan's Setup and ground rules, and from @iko:
8
8
9−- **The doc wins.** Where code and doc disagree, the doc stands until it changes. [spec/](spec/) is a snapshot; the doc itself is the authority.
9+- **The spec wins.** Where code and spec disagree, the spec stands until it changes. Until the Claude doc is synced with the repository's decisions, the spec is the copy in [spec/](spec/); the Synced column in [spec/decisions.md](spec/decisions.md) shows which rows the doc has.
10- **Language changes are agreed first** and recorded in the Decisions tab, before the code changes.
10- **Language changes are agreed first** and recorded in the Decisions tab, before the code changes.
11- **Questions go to @iko**, as comments on the doc, on the words they're about. While one is open, follow the most likely reading, mark it "(doc question)" in the library's notes, and list it in [open-questions.md](open-questions.md). Where an error points is not a doc question: the library's section 2.0 settles it.
11- **Questions go to @iko**, as comments on the doc, on the words they're about. While one is open, follow the most likely reading, mark it "(doc question)" in the library's notes, and list it in [open-questions.md](open-questions.md). Where an error points is not a doc question: the library's section 2.0 settles it.
12- **Every Jibb code block in the doc is a golden test**, and each stage's output is printed and compared. The doc labels its Jibb blocks `jibb`; `tools/doc-blocks` checks that each has its case.
12- **Every Jibb code block in the doc is a golden test**, and each stage's output is printed and compared. The doc labels its Jibb blocks `jibb`; `tools/doc-blocks` checks that each has its case.
13- **Each milestone ends with its checks passing on a fake ship**, not only under `urbit eval`.
13- **Each milestone ends with its checks passing on a fake ship**, not only under `urbit eval`.
14- **Push straight to `master`.** @iko reviews work in the project's chat, not in pull requests, so there are none. Run the checks below first.
14- **Push straight to `master`.** @iko reviews work in the project's chat, not in pull requests, so there are none. Run the checks below first.
15−- **Keep docs/ current**: [status.md](status.md) when a milestone moves, [open-questions.md](open-questions.md) when a question is settled or found.
15+- **Keep docs/ current**: [status.md](status.md) when a milestone moves, [open-questions.md](open-questions.md) when a question is found, and [spec/decisions.md](spec/decisions.md) when one is settled: it moves there.
16
16
17−The source-backed generic-union guard can be run under eval with `tools/type-union-source-test`; its `test-union-source` arm is also assembled for the fake ship. It checks a bounded partial inference slice, not general union completeness. `tools/type-union-alias-overlap-test` exercises the separate positive overlap witness and its shared ship test arm. `tools/type-full-overlap-test` checks structured full-module overlap evidence and the legacy error text under eval; both of its test arms are assembled for the fake ship.
17+The source-backed generic-union guard is the suite `tests/lib/jibb-union-source.hoon`: `tools/test-arms jibb-union-source` runs its `test-union-source` arm under eval, and the same arm is assembled for the fake ship. It checks a bounded partial inference slice, not general union completeness. `tests/lib/jibb-union-alias-overlap.hoon` exercises the separate positive overlap witness, with one test arm shared by eval and the ship. `tests/lib/jibb-full-overlap-basic.hoon` and `tests/lib/jibb-full-overlap-graph.hoon` check structured full-module overlap evidence and the legacy error text; `tools/test-arms 'jibb-full-overlap-*'` runs both of their test arms under eval, and both are assembled for the fake ship.
18
18
19## Setting up a machine
19## Setting up a machine
20
20
@@ -72,87 +72,108 @@ git clone https://github.com/urbit/tools /root/src/tools
72| --- | --- |
72| --- | --- |
73| `tools/check` | Runs every check in this table, or a group (`--group eval` or `ship`), or some by name: see [Before pushing](#before-pushing) |
73| `tools/check` | Runs every check in this table, or a group (`--group eval` or `ship`), or some by name: see [Before pushing](#before-pushing) |
74| `tools/golden` | Runs the golden cases under `urbit eval`: every case, or those matching `--case`; `--update` rewrites the expected outputs; `--show` prints them |
74| `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/importer-test` | Compares the partial Hoon importer's diagnostic trees and errors with `tests/importer/tree.txt` under `urbit eval` |
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) |
76−| `tools/type-import-default-test` | Compares default-wrapped union source proofs and adversarial cases under eval; the same golden runs on the ship |
77−| `tools/type-import-test` | Composes the Hoon importer with the partial checker and compares `tests/type-import/expected.txt` under eval |
78−| `tools/type-import-overlap-test` | Checks source-aware Hoon union overlap, provenance and proof-budget controls under eval; the same fixture runs on the ship |
79−| `tools/type-import-structural-test` | Checks multi-case and nested Hoon union overlap witnesses under eval and on the ship |
80−| `tools/type-union-source-test` | Checks bounded local generic-alias disjointness and state guards under eval and on the ship |
81−| `tools/type-union-alias-overlap-test` | Checks source-backed generic-alias overlap witnesses under eval and on the ship |
82−| `tools/type-full-overlap-test` | Checks structured full-module overlap evidence and imported-source attribution |
83−| `tools/type-tlon-test` | Runs the real Tlon presence source through the importer and partial checker, comparing `tests/type-tlon/expected.txt` under eval |
84−| `tools/type-import-diagnostic-test` | Compares the structured reader diagnostic bridge report under eval |
85−| `tools/type-mark-test` | Checks the partial checker’s mark import boundary against `tests/type-mark/expected.txt` under eval |
86−| `tools/type-poke-test` | Checks source-backed prelude and poke-only API reports against `tests/type-poke/expected.txt` under eval |
87−| `tools/type-api-paths-test` | Checks partial API path analysis with real todo mark samples against `tests/type-api-paths/expected.txt` under eval |
88−| `tools/type-api-evidence-test` | Runs source, scope, reader-result and declaration-watchability evidence guards under eval and on the ship |
89−| `tools/type-hole-guards-test` | Runs the shared hole-defaulting and API interface guards under eval; the same checks run on the ship |
90−| `tools/type-list-alias-test` | Runs the shared prelude list-alias and provenance guards under eval and on the ship |
91−| `tools/type-generic-recursion-test` | Checks source-backed generic recursive identity and provenance under eval and on the ship |
92−| `tools/type-generic-construction-test` | Checks source-backed one-layer recursive construction, provenance and fuel under eval and on the ship |
93−| `tools/type-generic-pattern-test` | Checks source-backed recursive patterns, catch-all coverage, state and per-attempt fuel/arm limits under eval and on the ship |
94−| `tools/type-deferred-test` | Checks the bounded source-owned deferred inference transaction under eval and on the ship |
95−| `tools/type-deferred-resolver-test` | Checks deferred resolution, report consistency and atomic failure under eval and on the ship |
96−| `tools/type-deferred-context-test` | Checks deferred source order and literal branch contexts under eval and on the ship |
97−| `tools/type-deferred-prepared-test` | Checks prepared-prelude tuple initializer recovery, exact partial reports and fail-closed guards under eval and on the ship |
98−| `tools/type-cell-branch-test` | Checks closed-cell branch context, rollback and bounded retry screens under eval and on the ship |
99−| `tools/type-generic-alias-test` | Runs public/private generic union alias and provenance guards under eval and on the ship |
100−| `tools/type-positional-face-guards-test` | Runs positional-call and nested-face guards under eval and on the ship |
101−| `tools/type-qath-guards-test` | Runs source-provenance, recursive unfolding and face guards under eval and on the ship |
102−| `tools/type-todo-partial-test` | Reports partial inference of the unchanged todo island through the real API and readers under eval and on the ship |
103−| `tools/type-todo-api-test` | Exercises the actual todo API through the real Hoon readers and partial checker |
104−| `tools/type-direct-gate-test` | Checks a synthetic source-backed program report and direct gate provenance under eval and on the ship |
105−| `tools/type-page-main-test` | Fully checks byte-identical static and direct data pages through real readers, exact main types, downstream imports and rejection guards under eval and on the ship |
106−| `tools/type-buttons-test` | Checks the documented valid button helpers and the unchanged unresolved-`%add` module through detailed and legacy inference under eval and on the ship |
107−| `tools/type-doc-examples-test` | Fully checks the import-only, view-day, step and cmd/sub doc fragments in their intended contexts through detailed and legacy inference under eval and on the ship |
108−| `tools/type-theme-test` | Fully checks the byte-identical real theme, its exact exported type, structural downstream import, dark absent/present forms and rejection guards under eval and on the ship |
109−| `tools/type-program-main-test` | Checks the narrow closed subscription-free program-main interface, downstream import and rejection guards under eval and on the ship |
110−| `tools/type-program-init-test` | Checks transactional direct-program initializer recovery, exact exported/imported types and fail-closed boundaries under eval and on the ship |
111−| `tools/type-program-update-test` | Checks transactional direct-program update result recovery, union/boolean context, exact exported/imported types and fail-closed boundaries under eval and on the ship |
112−| `tools/type-program-watch-test` | Checks direct singleton request-value watchability against merged real-todo evidence, exact types/imports and rejection boundaries under eval and on the ship |
113−| `tools/type-store-test` | Checks the unchanged cart/basket through detailed and legacy inference, exact store/derived schemes, malformed-prelude guards, structural imports, source-bound state watch evidence and rejection guards under eval and on the ship |
114−| `tools/type-todo-full-test` | Fully checks the byte-identical todo island and an ordinary call-bodied annotated-initializer variant through real readers, exact main types, structural downstream import and rejection controls under eval and on the ship |
115−| `tools/type-closed-gate-guards-test` | Checks closed gate sample labels and face uncertainty under eval and on the ship |
116−| `tools/type-constructor-fit-guards-test` | Checks constructor-case uncertainty and known mismatches under eval and on the ship |
117−| `tools/type-nested-union-guards-test` | Checks nested tagged-union case selection and uncertainty under eval and on the ship |
118−| `tools/type-empty-test` | Checks source-backed empty molds, inhabitedness, coverage and proof budgets under eval and on the ship |
119−| `tools/type-gate-free-guards-test` | Checks bounded gate-free verdicts, persistent constraints, substitution safeguards, collection keys and witness paths under eval and on the ship |
120−| `tools/type-gate-free-source-test` | Checks source-backed todo mold analysis through the real readers under eval and on the ship |
121−| `tools/type-sub-guards-test` | Checks source-backed subscription mold dependencies under eval and on the ship |
122−| `tools/type-ask-guards-test` | Runs ask origin and canonical list/unit bootstrap guards under eval and on the ship |
123−| `tools/type-request-guards-test` | Runs request evidence, source consistency and cache provenance guards under eval and on the ship |
124−| `tools/type-proj-guards-test` | Runs projection evidence, name-scope and dependency guards under eval and on the ship |
125−| `tools/type-arithmetic-guards-test` | Runs restricted atom-variable, unification and projection guards under eval and on the ship |
126−| `tools/type-module-scope-test` | Checks the partial module checker’s prelude boundary and duplicate-source rejection against `tests/type-module-scope/expected.txt` under eval |
127−| `tools/clay-fixtures` | Syncs `my-app`, builds its 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 |
76+| `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 |
128−| `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 |
77+| `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 |
129| `tools/doc-blocks` | Checks the doc's `jibb` blocks against the `doc-*` golden cases: `tools/doc-blocks docs/spec` |
78| `tools/doc-blocks` | Checks the doc's `jibb` blocks against the `doc-*` golden cases: `tools/doc-blocks docs/spec` |
130| `tools/ship` | Runs the fake ship: `start`, `stop`, `status`, `log`, `sync <desk>`, `assemble --out <dir>` (no ship needed), `test`, `gen-tests`, `check-commit`, `scry`, `hoon`, `run`, `poke`, `commit`, `mount`, `unmount` |
79| `tools/ship` | Runs the fake ship: `start`, `stop`, `status`, `log`, `sync <desk>`, `assemble --out <dir>` (no ship needed), `test`, `gen-tests`, `check-commit`, `scry`, `hoon`, `run`, `poke`, `commit`, `mount`, `unmount` |
131−| `tools/testdata/selftest` | Tests `tools/golden` and `tools/hoon` against a stub library, and `tools/doc-blocks` against Markdown it writes |
80+| `tools/testdata/selftest` | Tests `tools/golden` and `tools/hoon` against a stub library, `tools/test-arms` against the stub library with suites it writes, and `tools/doc-blocks` against Markdown it writes |
132| `tools/testdata/ship-selftest` | Tests `tools/ship`'s test generator and runner against a stub library on the ship |
81| `tools/testdata/ship-selftest` | Tests `tools/ship`'s test generator and runner against a stub library on the ship |
133−| `tools/testdata/clay-fixtures-selftest` | Tests temporary Clay fixture cleanup and signal handling without a ship |
134
82
135−`tools/golden` starts `urbit eval` once and builds the library, which takes about 8 s, then runs every case under `mule`, so a crash fails only its own case.
83+`tools/golden` starts `urbit eval` once and builds the library, which takes about 27 s, then runs every case under `mule`, so a crash fails only its own case.
84+
85+## The test suites
86+
87+Each file in `tests/lib` is a suite: a core of `test-` arms, with the libraries and files it reads bound by `/+` and `/*`. On the fake ship, `tools/ship test` runs every suite's arms with `-test /=jibb-dev=/tests`; under eval, `tools/test-arms` runs the same arms, so every suite below runs in both places. `tools/test-arms` gives each suite the subject Ford would give it on the `jibb-dev` desk: each `/+` library and each `/*` file, found where `tools/ship assemble` puts them. Before a suite's `|%` it takes only comments, `/+` lines and `/*` lines, and binds only `%txt` and `%jibb` files. The suites it runs share one eval, so the library is built once for all of them, in about 17 s with `!:`, and so is the importer library `jibb-import`, in about 20 s more, when any of them uses it. Each arm runs under `mule` and prints `OK`, `FAILED` or `CRASHED`, as `-test` does; a crashed arm's trace is mapped to lines in the suite and the library, with an excerpt of the innermost spot. When a suite doesn't build, `tools/test-arms` runs the suites again one at a time and reports it as `FAILED <suite> (build)`, with its error placed in the suite file. `tools/test-arms <suite>` runs one suite, and names or globs pick several, as `tools/test-arms jibb-store 'jibb-program-*'`; `tools/test-arms --list` prints the suites and their arms. `tools/check` runs them all in four shards, `arms-1` to `arms-4`, each `tools/test-arms --shard I/4` in an eval of its own, balanced by the measured costs in `COSTS` and `LIB_COSTS` in `tools/test-arms`. `tests/lib/jibb.hoon`, which `tools/ship gen-tests` writes from `tests/golden`, is left out under eval, since `tools/golden` runs those cases.
88+
89+A 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.
90+
91+The `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`.
92+
93+| Suite | What it checks | Golden files |
94+| --- | --- | --- |
95+| `jibb-api-evidence` | Source, scope, reader-result and declaration-watchability evidence guards for path declarations, in two arms, over synthetic and real todo inputs | |
96+| `jibb-api-paths` | Partial API path analysis with real todo mark samples; it does not generate request interfaces | `tests/type-api-paths/expected.txt` |
97+| `jibb-arithmetic-guards` | Restricted atom-variable, unification and projection guards | |
98+| `jibb-ask-guards` | Ask origin and canonical list/unit bootstrap guards | |
99+| `jibb-bridge` | The importer/checker bridge: the Hoon importer composed with the partial checker | `tests/type-import/expected.txt` |
100+| `jibb-buttons` | The documented valid button helpers and the unchanged unresolved-`%add` module, through detailed and legacy inference | `tests/type-buttons/expected.txt` |
101+| `jibb-cell-branch` | Closed-cell branch context, rollback and bounded retry screens | |
102+| `jibb-check-spans` | `+check-spans`, which `+golden` runs on every tree: its own test, `+check-spans-test`, moves the spans of parsed nodes as a parser bug would and checks that it says so | |
103+| `jibb-closed-gate-guards` | Closed gate sample labels and face uncertainty | |
104+| `jibb-constructor-fit-guards` | Constructor-case uncertainty and known mismatches | |
105+| `jibb-deferred` | The bounded source-owned deferred inference transaction | `tests/type-deferred/expected.txt` |
106+| `jibb-deferred-context` | Deferred source order and literal branch contexts | `tests/type-deferred-context/report.txt` |
107+| `jibb-deferred-prepared` | Prepared-prelude tuple initializer recovery, exact partial reports and fail-closed guards | `tests/type-deferred-prepared/expected.txt`, `expected-control.txt` and `expected-tuple-only.txt` |
108+| `jibb-deferred-resolver` | Deferred resolution, report consistency and atomic failure | `tests/type-deferred-resolver/expected.txt` |
109+| `jibb-direct-gate-guards` | Direct gate provenance: direct layout evidence keeps its provenance and final face constraints | |
110+| `jibb-direct-gate-source` | A synthetic source-backed program report: direct-source gate layouts through a synthetic program scaffold | `tests/type-direct-gate/expected.txt` |
111+| `jibb-doc-examples` | Full checking of the import-only, view-day, step and cmd/sub doc fragments in their intended contexts, through detailed and legacy inference | |
112+| `jibb-empty` | Source-backed empty molds, inhabitedness, coverage and proof budgets | `tests/type-empty/expected.txt` |
113+| `jibb-full-overlap-basic` | Structured full-module overlap evidence: source-bound overlap witnesses, generic parameter limits, precedence and rejection controls, and the legacy full-module error text | `tests/type-full-overlap/expected-basic.txt` |
114+| `jibb-full-overlap-graph` | Imported-source attribution of overlap evidence across parent and child modules: cache rebuilds and source binding, and private, cyclic, duplicate, missing and transitive imports | `tests/type-full-overlap/expected-graph.txt` |
115+| `jibb-gate-free-guards` | Bounded gate-free verdicts, persistent constraints, substitution safeguards, collection keys and witness paths | |
116+| `jibb-gate-free-source` | Source-backed todo mold analysis through the real readers | `tests/type-gate-free/expected.txt` |
117+| `jibb-generic-alias` | Public/private generic union alias and provenance guards | |
118+| `jibb-generic-construction` | Source-backed one-layer recursive construction, provenance and fuel | `tests/type-generic-construction/expected.txt` |
119+| `jibb-generic-pattern` | Source-backed recursive patterns, catch-all coverage, state and per-attempt fuel/arm limits | `tests/type-generic-pattern/expected.txt` |
120+| `jibb-generic-recursion` | Source-backed generic recursive identity and provenance | `tests/type-generic-recursion/expected.txt` |
121+| `jibb-hole-guards` | Hole-defaulting and API interface guards | |
122+| `jibb-hoon-reference` | Hoon translations of the Jibb-written `zing`, `lead`, `late` and `succ` against Hoon's own arms, on selected inputs; this does not execute Jibb, test lowering or prove jet recognition | |
123+| `jibb-import` | The partial Hoon importer's diagnostic trees and errors over the importer fixtures, and the structured values behind them; the projection is an internal tree, not the Jibb type printer | `tests/importer/tree.txt` |
124+| `jibb-import-default` | Default-wrapped union source proofs over a real Tlon mold, and adversarial cases | `tests/type-import-default/expected.txt` |
125+| `jibb-import-diagnostic` | The structured reader diagnostic bridge report: definite and unsupported reader diagnostics through the checker | `tests/type-import-diagnostic/expected.txt` |
126+| `jibb-import-overlap` | Source-aware Hoon union overlap, provenance and proof-budget controls | `tests/type-import-overlap/expected.txt` |
127+| `jibb-import-structural` | Multi-case and nested Hoon union overlap witnesses | `tests/type-import-structural/expected.txt` |
128+| `jibb-list-alias-guards` | Prelude list-alias and provenance guards | `tests/type-list-alias/expected.txt` |
129+| `jibb-mark-bridge` | The partial checker's mark import boundary | `tests/type-mark/expected.txt` |
130+| `jibb-module-scope` | The partial module checker's prelude boundary and duplicate-source rejection | `tests/type-module-scope/expected.txt`, and the golden case's `tests/golden/types-prelude-interface/types.txt` |
131+| `jibb-nested-union-guards` | Nested tagged-union case selection and uncertainty | |
132+| `jibb-page-main` | Full checking of byte-identical static and direct data pages through real readers, exact main types, downstream imports and rejection guards | |
133+| `jibb-poke-bridge` | Source-backed prelude and poke-only API reports | `tests/type-poke/expected.txt` |
134+| `jibb-positional-face-guards` | Positional-call and nested-face guards | |
135+| `jibb-program-init` | Transactional direct-program initializer recovery, exact exported/imported types and fail-closed boundaries | |
136+| `jibb-program-main` | The narrow closed subscription-free program-main interface, downstream import and rejection guards | |
137+| `jibb-program-update` | Transactional direct-program update result recovery, union/boolean context, exact exported/imported types and fail-closed boundaries | |
138+| `jibb-program-watch` | Direct singleton request-value watchability against merged real-todo evidence, exact types/imports and rejection boundaries | |
139+| `jibb-proj-guards` | Projection evidence, name-scope and dependency guards | |
140+| `jibb-qath-fuel` | Recursive qath unfolding and face guards: unfolding uses bounded fuel and keeps uncertain faces | |
141+| `jibb-qath-source` | Qath source-provenance guards: source-backed qath accepts only the proven public and internal interfaces | |
142+| `jibb-request-guards` | Request evidence, source consistency and cache provenance guards | |
143+| `jibb-store` | The unchanged cart/basket through detailed and legacy inference, exact store/derived schemes, malformed-prelude guards, structural imports, source-bound state watch evidence and rejection guards | |
144+| `jibb-sub-guards` | Source-backed subscription mold dependencies | |
145+| `jibb-theme` | Full checking of the byte-identical real theme, its exact exported type, structural downstream import, dark absent/present forms and rejection guards | |
146+| `jibb-tlon-bridge` | The real, unmodified Tlon presence source through the importer and partial checker | `tests/type-tlon/expected.txt` |
147+| `jibb-todo-api` | The actual todo API through the real Hoon readers and partial checker | `tests/type-todo-api/expected.txt` and `negative-expected.txt` |
148+| `jibb-todo-full` | Full checking of the byte-identical todo island and an ordinary call-bodied annotated-initializer variant through real readers, exact main types, structural downstream import and rejection controls | `tests/type-todo-full/expected.txt` |
149+| `jibb-todo-partial` | Partial inference reports for the unchanged todo island through the real API and readers | `tests/type-todo-partial/expected.txt` |
150+| `jibb-typecheck` | The partial inference unifier, through the library's own `+itype-unify-test` cases | `tests/checker/unification.txt` |
151+| `jibb-union-alias-overlap` | Source-backed generic-alias overlap witnesses | `tests/type-union-alias-overlap/expected.txt` |
152+| `jibb-union-source` | Bounded local generic-alias disjointness and state guards | `tests/type-union-source/expected.txt` |
153+
154+`jibb-deferred` exercises the bounded, source-owned constructor transaction and low-level freshness/replay guards. `jibb-deferred-resolver` checks the experimental import-free library resolver, report consistency, atomic failure, and that both source orders of a late face constraint decline. `jibb-deferred-prepared` checks the separate partial-report-only prepared-prelude route, direct tuple-literal obligations, exact report types and its wrong-field, unrelated-tag, mold-collision and no-final-cast controls. These suites do not establish island-kind or watchability support.
136
155
137## Before pushing
156## Before pushing
138
157
139```
158```
140tools/check # every check; it exits 0 only when all pass
159tools/check # every check; it exits 0 only when all pass
141−tools/check --group eval # only the checks that need no ship, as CI runs them
160+tools/check --group eval # only the checks that need no ship
142nix flake check # the same checks in the Nix sandbox, on a fresh fake ~zod
161nix flake check # the same checks in the Nix sandbox, on a fresh fake ~zod
143```
162```
144
163
145−`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. The eval group, the 62 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 'type-todo-*'`. A failing check's output follows its FAIL line; `-v` prints every check's output, and `--logs DIR` keeps it all.
164+`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.
165+
166+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).
146
167
147`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.
168`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.
148
169
149−`tools/ship test` regenerates `tests/lib/jibb.hoon` and syncs the `jibb-dev` desk before it runs, so commit the regenerated file. Sync preflights and splits large deletion lists into bounded click requests, waiting for each Clay revision; a failure stops later batches. The ship self-test exercises this when switching from the full desk to a smaller fixture desk. A run with `--stub`, `--lib`, or a custom `--golden` isolates its generated golden tests from the repository's other test programs; run the default command afterward to restore and test those programs. It also runs the independent `tests/lib/jibb-import.hoon` test against the same importer fixtures and expected diagnostic projection as `tools/importer-test`. The projection is an internal tree, not the Jibb type printer. `tests/lib/jibb-bridge.hoon` also runs the importer/checker bridge fixture on the ship; `tools/type-import-test` runs the same report under eval. `tests/lib/jibb-tlon-bridge.hoon` and `tools/type-tlon-test` run the real Tlon presence reader/checker fixture on both. The structured reader diagnostics have their own `tests/lib/jibb-import-diagnostic.hoon` ship test and `tools/type-import-diagnostic-test` eval test. The mark bridge has its own `tests/lib/jibb-mark-bridge.hoon` ship test and `tools/type-mark-test` eval test; both compare the same fixture report. `tests/lib/jibb-poke-bridge.hoon` and `tools/type-poke-test` share the source-backed prelude and poke-only API fixture. `tests/lib/jibb-api-paths.hoon` and `tools/type-api-paths-test` share partial path analysis over the real todo marks; this does not generate request interfaces. `tests/lib/jibb-module-scope.hoon` and `tools/type-module-scope-test` compare the prelude scope report on the ship and under eval.
170+`tools/ship test` regenerates `tests/lib/jibb.hoon` and syncs the `jibb-dev` desk before it runs. The file is ignored by git, since desk assembly always regenerates it. Sync preflights and splits large deletion lists into bounded click requests, waiting for each Clay revision; a failure stops later batches. The ship self-test exercises this when switching from the full desk to a smaller fixture desk. A run with `--stub`, `--lib`, or a custom `--golden` isolates its generated golden tests from the repository's other test programs; run the default command afterward to restore and test those programs. `tools/ship test` also runs every other suite in `tests/lib`, and `tools/test-arms` runs the same suites under eval, so each compares the same fixtures and golden files in both places. `tests/lib/jibb-import.hoon` runs the importer fixtures against their expected diagnostic projection, an internal tree, not the Jibb type printer, and checks the structured values behind it. The probes it runs live in the suite, not in `jibb-dev/lib/jibb-import.hoon`, which app desks vendor. `tests/lib/jibb-bridge.hoon` runs the importer/checker bridge fixture, and `tests/lib/jibb-tlon-bridge.hoon` the real Tlon presence reader/checker fixture. `tests/lib/jibb-import-diagnostic.hoon` covers the structured reader diagnostics, and `tests/lib/jibb-mark-bridge.hoon` compares the mark bridge's fixture report. `tests/lib/jibb-poke-bridge.hoon` holds the source-backed prelude and poke-only API fixture. `tests/lib/jibb-api-paths.hoon` runs partial path analysis over the real todo marks; this does not generate request interfaces. `tests/lib/jibb-module-scope.hoon` compares the prelude scope report.
150
171
151## Golden cases
172## Golden cases
152
173
153A case is a folder `tests/golden/<name>/` holding:
174A case is a folder `tests/golden/<name>/` holding:
154
175
155−- `source.jibb`, the input, ending in one newline;
176+- `source.jibb`, the input, ending in one newline. A case whose input is a `my-app` file, such as a doc block that `my-app` holds, makes it a symlink to that file; desk assembly leaves the link out, and `tools/ship gen-tests` reads the file from `/my-app`. A file under `modules/` may link to `my-app` the same way;
156- `about.txt`: a `source:` line with the doc's words or block it comes from, a `tests:` line saying what it exercises, and an `expect:` line, either `parses` or `error at <line>:<col>` and why (one case, `inline-leftout-signed-float-auras`, says `unclear`: see grammar question 13 in [open-questions.md](open-questions.md));
177- `about.txt`: a `source:` line with the doc's words or block it comes from, a `tests:` line saying what it exercises, and an `expect:` line, either `parses` or `error at <line>:<col>` and why (one case, `inline-leftout-signed-float-auras`, says `unclear`: see grammar question 13 in [open-questions.md](open-questions.md));
157- the expected outputs, `tokens.txt` and `tree.txt`, each the output plus one newline.
178- the expected outputs, `tokens.txt` and `tree.txt`, each the output plus one newline.
158- optionally, `path.txt`, the logical `/ui/.../*.jibb` path to pass to the compiler; the source remains `source.jibb`.
179- optionally, `path.txt`, the logical `/ui/.../*.jibb` path to pass to the compiler; the source remains `source.jibb`.
@@ -185,5 +206,3 @@ Write `source.jibb` and `about.txt` by hand, run `tools/golden --update --case <
185## Commits
206## Commits
186
207
187A short subject in the imperative, then a body that says what changed and why, wrapped at 72 columns, as in `git log`. Each commit leaves every check passing.
208A short subject in the imperative, then a body that says what changed and why, wrapped at 72 columns, as in `git log`. Each commit leaves every check passing.
188−
189−`tools/type-deferred-test` exercises the bounded, source-owned constructor transaction and low-level freshness/replay guards. `tools/type-deferred-resolver-test` checks the experimental import-free library resolver, report consistency, atomic failure, and that both source orders of a late face constraint decline. `tools/type-deferred-prepared-test` checks the separate partial-report-only prepared-prelude route, direct tuple-literal obligations, exact report types and its wrong-field, unrelated-tag, mold-collision and no-final-cast controls. These checks do not establish island-kind or watchability support.
docs/open-questions.md+6−52
@@ -1,6 +1,6 @@
1# Open questions
1# Open questions
2
2
3−Questions the doc doesn't settle yet, as of 2026-10-30. Language questions belong to the doc's author, @iko: the plan says they go "as comments on the doc, on the words they're about", and a change to the language is "agreed first and recorded in Decisions". When one is settled, record it there, change the code if needed, and remove it here.
3+Questions the doc doesn't settle yet, as of 2026-11-02. Language questions belong to the doc's author, @iko: the plan says they go "as comments on the doc, on the words they're about", and a change to the language is "agreed first and recorded in Decisions". When one is settled, record it there, change the code if needed, and move it from here to [Decisions](spec/decisions.md), which holds the settled ones.
4
4
5## The plan's open questions
5## The plan's open questions
6
6
@@ -14,57 +14,13 @@ From [spec/implementation-plan.md](spec/implementation-plan.md), Open questions:
14| Are the proposed loop rules adopted, along with no overlays in v1? | Milestone 6 |
14| Are the proposed loop rules adopted, along with no overlays in v1? | Milestone 6 |
15| What do controls look like by default: buttons, toggles and fields, with their focus and disabled states? | Milestone 6 |
15| What do controls look like by default: buttons, toggles and fields, with their focus and disabled states? | Milestone 6 |
16
16
17−On 2026-10-30, @iko adopted gate-free `eq` arguments and map and set keys, treating gates as opaque when distinguishing union cases, and rejecting a non-gate value that depends on itself even through a gate. The checker infers and generalizes the gate-free constraint. @iko also said jetted prelude functions may take gates.
18−
19## Questions milestone 2 raises
17## Questions milestone 2 raises
20
18
21−Found while writing [prompts/milestone-2.md](prompts/milestone-2.md), checking it against the doc's examples, and building the checker. The numbering is retained so existing references stay valid. Question 3 remains open; the field-order detail in question 32 is being clarified. The other questions are settled.
19+Found while writing [prompts/milestone-2.md](prompts/milestone-2.md), checking it against the doc's examples, and building the checker. Question 3 remains open, and the field-order detail in question 32. The others are settled and are in [Decisions](spec/decisions.md#settled-milestone-2-questions), which keeps their numbers, so existing references stay valid.
22−
23−1. **Settled: how the prelude identifies jetted functions.** On 2026-10-30, @iko said the prelude functions have working Jibb implementations, and the compiler recognizes their shapes and uses the Hoon versions so jets can fire.
24−2. **Settled: how the prelude keeps helpers private.** On 2026-10-30, @iko chose a separate internal prelude module imported by the prelude, without exposing the imported helpers.
25−3. **The prelude's inventory.** On 2026-10-30, @iko chose to include all names from the listed Hoon library sections, excluding groups the spec explicitly leaves out. All of 3g is included; its Hoon `tone` is exposed as `tone.hoon`, distinct from the styling type. Hoon 1c `step` is exposed as `step.hoon`, leaving the Grammar example's `step` name available. On 2026-10-30, @iko also approved `%$` as a term literal and pattern, so Jibb can write the `%$` case of Hoon `coin`. For parsing sections 4j and 4l, only the explicitly listed `slav` and `slaw` are included; other parser helpers are left out. Jibb's `not` negates a loobean, and Hoon's bitwise `not` is exposed as `not.bit`. @iko also agreed to specifying the complete exported inventory in the doc, building its types and gates needed by the examples in milestone 2, and doing native implementations in milestone 3. Prelude unions such as spaces, roles and tones need names that other modules cannot shadow. The actual inventory and signatures still need to be specified.
26−4. **Settled: a capital in a local `++`.** On 2026-10-30, @iko said it shares the enclosing `++`'s variable of that name if the enclosing `++` also uses it; otherwise the local `++` introduces and generalizes its own variable. For example, `++ inner |= y=A y` shares `A` with an enclosing gate whose sample is `x=A`, but generalizes its own `A` if the enclosing `++` does not use `A`. A different type uses a different capital. The Grammar and Decisions record this alongside the earlier aura rules.
27−5. **Settled: cells of no items or one.** On 2026-10-30, @iko said a single-item cell is the value and `[]` is an error. The theme's `dark=[tones=[…]]`, a record of one field, must still check.
28−6. **Settled: a change with no items.** On 2026-10-30, @iko said `m()` is an error. The parser still accepts it; the checker needs to reject it and add a golden case.
29−7. **Settled: the doc's blocks that aren't whole modules.** On 2026-10-30, @iko agreed to check each in its intended context: the `cmd` and `sub` definitions as prelude source, the Core language tab's `update` inside the todo island, and the Grammar's imports example against fixture files.
30−8. **Settled: tuples and records.** On 2026-10-30, @iko agreed that an unnamed position can unify with a faced position and take its face; two different explicit faces still conflict. The Grammar and Decisions record this rule.
31−9. **Settled: values where `*` is expected.** On 2026-10-30, @iko said `*` is the noun type, not a type variable; generic positions use proper type variables. A value already known to be `@ud` can be passed where `*` is expected. The `each` and `table` signatures use `key=K`.
32−10. **Settled: navigation commands.** On 2026-10-30, @iko chose separate declarations for application paths and unchecked cords, with `link-unsafe`, `image-unsafe` and `go-unsafe` for the unchecked forms. `image-unsafe` takes a sized URL record. Both navigation declarations produce `[%go url=@t]`; `go` converts the application path to a cord including the app's base path.
33−11. **Settled: stores and derived gates.** On 2026-11-01, @iko said a store's local `+$ poke` is an ordinary action mold and the runtime envelope is `raw-poke`; a derived name clashes with an import face; and an island watching a request whose case has a separate `scry=` path has a type error. The todo API's request is renamed `todo-by-id` so it does not clash with `/- todo`. The checker must account for the fact that a store's kind is determined by the type of `main`.
34−12. **Settled: how to print a union without a name.** On 2026-10-30, @iko said to print its cases separated by spaces, as `%approve %deny`. This is print-only, not Jibb syntax.
35−13. **Settled: how to print type constraints.** On 2026-10-30, @iko chose `$-([A A] A) where A is an atom` for an atom constraint and `$-([A A] ?) where A contains no gates` for a gate-free constraint. Multiple clauses are comma-separated, as `where A is an atom, B contains no gates`.
36−14. **Settled: how the prelude implements foundational operations.** On 2026-10-30, @iko chose private low-level primitives in the internal prelude module, with the public foundational gates implemented in Jibb on top of them.
37−15. **Settled: unrestricted atoms and shared auras.** On 2026-10-30, @iko said `@` means any atom, independently at each occurrence, so Hoon `dime` and `pint` keep their bare-`@` fields. A specific atom such as `@ud` fits where `@` is expected; an `@` value needs a check to fit `@ud`. Shared atom types use one capital, with the atom constraint inferred from its body, as for `add` taking `[A A]` and returning `A`.
38−16. **Settled: loobeans in union disjointness.** On 2026-10-30, @iko said `?` counts as its two atoms, `%.y` and `%.n`: it is disjoint from any cell and overlaps the constants 0 and 1.
39−17. **Settled: empty cases in union disjointness.** On 2026-10-30, @iko said `!!` is disjoint from every case. A cell containing an empty position at any depth is itself empty and is also disjoint from every case.
40−18. **Settled: the value gate `like`.** On 2026-10-31, @iko chose a gate `(like convert result)` that maps the product of an existing `(like A)` result with `convert=$-(A B)`, yielding `(like B)` while preserving its position and remaining input. An absent result stays absent. The `(like A)` mold remains available in the separate mold namespace. Hoon's wet `+like` instead builds a gate that constructs a result from an input noun; the chosen Jibb value gate is an adaptation of that behavior.
41−19. **Settled: Hoon aura families and `step.hoon`.** On 2026-10-30, @iko chose `step.hoon` for Hoon 1c `step`, avoiding a clash with the Grammar example's `step`, and chose one-way widening across Hoon aura families: for example, `@ud` and `@ux` fit `@u`, and `@tD` fits `@t`. The reverse needs a check. The `step.hoon` group representation is not implemented yet.
42−20. **Settled: the type of `clap`.** On 2026-10-30, @iko chose one shared value type for both units and the combining gate. If either unit is absent, `clap` returns the other; if both are present, it applies the gate to their values and wraps the result.
43−21. **Settled: duplicate faces in imported Hoon records.** On 2026-10-30, @iko chose to reject an imported Hoon record with duplicate field names where its type is used. Hoon permits `[a=@ud a=@t]` and picks the first `a`; Jibb rejects it.
44−22. **Settled: overlapping imported `$%` and `$?` cases.** On 2026-10-30, @iko confirmed that the general union disjointness rule rejects imported `$%` and `$?` cases that overlap as nouns where the type is used, as it does for `$^`. The importer rejects recognizable overlaps and fails closed when it cannot verify them.
45−23. **Settled: converging explicit capitals.** On 2026-10-30, @iko chose that a body cannot force two separately written capitals to be equal. For `++ repeated |= x=(choice A A) x`, `++ f |= x=(choice A B) (repeated x)` is an error; use `A` in both positions when the type must be shared. This also applies across local captures and within generic mold applications.
46−
47−24. **Settled: how the internal prelude provides `raw-poke`.** On 2026-11-01, @iko chose to define `raw-poke` in the source-backed private internal prelude module and re-export it through the public prelude as an ordinary transparent type. Ordinary modules can construct and inspect its values, while derived API/store `poke` helpers return commands. This settles `raw-poke`; it does not decide the representation of `ask` or `qath`.
48−
49−25. **Settled: how the prelude provides `ask` and `qath`.** On 2026-10-31, @iko chose ordinary transparent types defined in the internal prelude and re-exported normally, as for `raw-poke`. Callers may construct and inspect their values.
50−
51−26. **Settled: the `step` example's `at` binder.** On 2026-10-31, @iko chose to rename the `describe` pattern binder to `sent-at`, keeping Hoon's `at` in the prelude and the no-shadowing rule.
52−
53−27. **Settled: duplicate fields in a Jibb-written record.** On 2026-10-31, @iko chose to reject duplicate field names, as for imported Hoon records.
54
20
55−28. **Settled: arithmetic on loobeans.** On 2026-10-31, @iko chose to reject loobean operands for arithmetic. Comparison may still accept loobeans and returns `?`. The checker needs to retain this constraint through inference, generalization and instantiation before it exports `add` or `dec`.
21+**3. The prelude's inventory.** On 2026-10-30, @iko chose to include all names from the listed Hoon library sections, excluding groups the spec explicitly leaves out. All of 3g is included; its Hoon `tone` is exposed as `tone.hoon`, distinct from the styling type. Hoon 1c `step` is exposed as `step.hoon`, leaving the Grammar example's `step` name available. On 2026-10-30, @iko also approved `%$` as a term literal and pattern, so Jibb can write the `%$` case of Hoon `coin`. For parsing sections 4j and 4l, only the explicitly listed `slav` and `slaw` are included; other parser helpers are left out. Jibb's `not` negates a loobean, and Hoon's bitwise `not` is exposed as `not.bit`. @iko also agreed to specifying the complete exported inventory in the doc, building its types and gates needed by the examples in milestone 2, and doing native implementations in milestone 3. Prelude unions such as spaces, roles and tones need names that other modules cannot shadow. The actual inventory and signatures still need to be specified.
56
22
57−29. **Settled: printing the arithmetic atom constraint.** On 2026-10-31, @iko chose `where A is an atom other than ?` for a generic arithmetic type whose atom variable excludes loobeans.
58−
59−30. **Settled: a hole inferred as a generic variable.** On 2026-10-31, @iko said a hole resolved to an explicitly written type variable counts as inferred: in `++ id |= x=A ^- _ x`, the result hole is `A`. Named molds must determine their own holes without constraints from later uses; an unconstrained hole is an error.
60−
61−31. **Settled: uses of a value with a hole.** On 2026-10-31, @iko said a value definition must determine its own holes; another definition's use cannot fix an otherwise unresolved hole. For example, `++ id |= x=_ x` remains an error even if a later definition calls `id` with a cord.
62−
63−32. **Partly settled: type-directed record projection.** On 2026-10-31, @iko chose an explicit `(proj record)` whose expected result type selects the fields. There is no automatic projection, and `proj` is reserved against definitions and imports. The result contains exactly the fields of its expected type. Whether the result may reorder fields from the source remains open.
23+**32. Partly settled: type-directed record projection.** On 2026-10-31, @iko chose an explicit `(proj record)` whose expected result type selects the fields. There is no automatic projection, and `proj` is reserved against definitions and imports. The result contains exactly the fields of its expected type. Whether the result may reorder fields from the source remains open.
64−
65−33. **Settled: watching a request with unknown provenance.** On 2026-10-31, @iko said an island may watch a request only if the checker proves it watchable at compile time. An unknown request, including one built or passed through a gate without sufficient evidence, is rejected rather than deferred to a runtime check.
66−
67−34. **Settled: constructors and equal noun literals.** On 2026-10-31, @iko said expressions with the same runtime representation count as equal, and cases that cannot be distinguished at runtime are rejected at compile time. Thus `|=%$` matches a case headed by `%$`, `%.y` or `~`: each is the noun 0. Cases with equal heads and overlapping payloads cannot coexist in a union.
68
24
69## Review rulings waiting for @iko
25## Review rulings waiting for @iko
70
26
@@ -85,8 +41,6 @@ The [2026-11-02 review](reviews/2026-11-02-repo-review.md) raised these language
85| [27](reviews/2026-11-02-questions.md) | Should the `%jibb` mark keep dropping the final newline on a `%txt` round trip? | Keep it, like `%hoon` | A61 |
41| [27](reviews/2026-11-02-questions.md) | Should the `%jibb` mark keep dropping the final newline on a `%txt` round trip? | Keep it, like `%hoon` | A61 |
86| [28](reviews/2026-11-02-questions.md) | Should the printer flatten `[a [b c]]` and print named molds by name, such as `theme`? | Yes | A136 |
42| [28](reviews/2026-11-02-questions.md) | Should the printer flatten `[a [b c]]` and print named molds by name, such as `theme`? | Yes | A136 |
87
43
88−Question 25, when to build `eq` and the gate-free constraint, is settled: @iko's commit 0858191 adds `eq` and infers the constraint.
89−
90## Grammar questions never put to the doc's author
44## Grammar questions never put to the doc's author
91
45
92In milestone 1 the parser met about thirty places where the doc could be read more than one way. Twelve went to @iko on 2026-10-30 and are rows of the Decisions tab. These were not asked. For each, the parser follows the reading below, and some are marked "(doc question)" in the library's notes. None changes what a valid program means, except where a reading makes something an error.
46In milestone 1 the parser met about thirty places where the doc could be read more than one way. Twelve went to @iko on 2026-10-30 and are rows of the Decisions tab. These were not asked. For each, the parser follows the reading below, and some are marked "(doc question)" in the library's notes. None changes what a valid program means, except where a reading makes something an error.
@@ -96,14 +50,14 @@ In milestone 1 the parser met about thirty places where the doc could be read mo
96| 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 |
50| 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 |
97| 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`) |
51| 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`) |
98| 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)" |
52| 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)" |
99−| 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) |
100| 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`" |
54| 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`" |
101| 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`) |
55| 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`) |
102| 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" |
56| 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" |
103| 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 |
57| 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 |
104| 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 |
58| 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 |
105| 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 |
59| 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 |
106−| 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 |
107| 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-*`) |
61| 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-*`) |
108| 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" |
62| 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" |
109
63
docs/prelude-inventory.md+1−1
@@ -158,7 +158,7 @@ The following shapes can be written as Jibb declarations once their referenced p
158 [%2 p=(list tank)]
158 [%2 p=(list tank)]
159```
159```
160
160
161−The compiler-result `tone.hoon` has the three cases listed above; the qualified name is a prelude group member, not a `+$` identifier containing a dot. Question 15 in [open-questions.md](open-questions.md) records @iko's decision that `@` is an unrestricted atom, resolving the `dime` and `pint` mismatch. The source-backed value form of `like` maps an existing result's product. Supported calls infer in the partial checker; complete checking and backend validation for `like` and `wonk` remain outstanding.
161+The compiler-result `tone.hoon` has the three cases listed above; the qualified name is a prelude group member, not a `+$` identifier containing a dot. Question 15 in [Decisions](spec/decisions.md#settled-milestone-2-questions) records @iko's decision that `@` is an unrestricted atom, resolving the `dime` and `pint` mismatch. The source-backed value form of `like` maps an existing result's product. Supported calls infer in the partial checker; complete checking and backend validation for `like` and `wonk` remain outstanding.
162
162
163## 4a
163## 4a
164
164
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.
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/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
234
234
235**Answer:** a *(chosen)*
235**Answer:** a *(chosen)*
236
236
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+
237**31. How should the 28 copies of `my-app` files under `tests/` be handled?** (A108, A109)
239**31. How should the 28 copies of `my-app` files under `tests/` be handled?** (A108, A109)
238
240
239- a) Map `my-app` into the `jibb-dev` desk outside `/tests` and read it directly, removing the copies.
241- 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
6
6
7This 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).
7This 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).
8
8
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+
9## Summary
23## Summary
10
24
11- **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.
25- **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-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
83| `/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 |
83| `/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 |
84| `title.p`, `space.theme.theme` | `slot` at the field's axis, nested for longer wings |
84| `title.p`, `space.theme.theme` | `slot` at the field's axis, nested for longer wings |
85| `(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 |
85| `(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 |
86| `card.card`, an import | The qualified name `components/card:card` |
87| `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 |
88| `f a b c` | `(app f (cons a (cons b c)))`: the arguments are the sample |
89| `f a b c` | `(app f (cons a (cons b c)))`: the arguments are the sample |
89| `\|= [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 |
90| `\|= [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 |
90| `\|=%got` | `(lam _1 (cons %got _1))` |
91| `\|=%got` | `(lam _1 (cons %got _1))` |
@@ -104,14 +105,14 @@ The todo island's `update`, from worked example 3:
104```jibb
105```jibb
105++ update |= [=msg m=model]
106++ update |= [=msg m=model]
106 ?- msg
107 ?- msg
107− [%typed t]
108+ [%typed t]
108− ?- (gth (lent (tuba (trip t))) 80)
109+ ?- (gth (lent (tuba (trip t))) 80)
109− %.y [m(draft=t error=`"Too long") ~]
110+ %.y [m(draft=t error=`"Too long") ~]
110− %.n [m(draft=t error=~) ~]
111+ %.n [m(draft=t error=~) ~]
111− %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
112+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
112− [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
113+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
113− [%got ts] [m(todos=ts) ~]
114+ [%got ts] [m(todos=ts) ~]
114− [%acked err] [m(error=err) ~]
115+ [%acked err] [m(error=err) ~]
115```
116```
116
117
117lowers 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.
118lowers 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+167−90
@@ -6,96 +6,173 @@ The choices behind the Language tab, made on 2026-10-23; a later date marks a re
6
6
7## Decisions
7## Decisions
8
8
9−| Decision | Choice | Status |
9+Until 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.
10−| --- | --- | --- |
10+
11−| 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 |
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−| 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 |
12+
13−| Cells | A single-item cell `[a]` is `a`; an empty `[]` is an error, in expressions and molds | Decided 2026-10-30 |
13+| Decision | Choice | Status | Synced |
14−| Numeric terms | `%` and a decimal as Hoon writes it: `%1.000`; `%1000` and `%007` are errors | Decided 2026-10-30 |
14+| --- | --- | --- | --- |
15−| 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 |
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−| Spacing | Style, kept by the formatter: one or more spaces between items, and spaces allowed after an opener, before a closer and at the end of a line; faces, puns and typed path segments take no spaces; a rune is followed by one | Decided 2026-10-30 |
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 |
17−| Path literals | `/posts/~zod` is an expression: `pathlit` is an operand | Decided 2026-10-30 |
17+| Cells | A single-item cell `[a]` is `a`; an empty `[]` is an error, in expressions and molds | Decided 2026-10-30 | Check |
18−| Crash | `!!` is an operand, so `f !!` and `~[!!]` need no parentheses | Decided 2026-10-30 |
18+| Numeric terms | `%` and a decimal as Hoon writes it: `%1.000`; `%1000` and `%007` are errors | Decided 2026-10-30 | Check |
19−| Sample names | Every bare name in a sample binds, at any depth: `\|= [a=@ b]` binds `a` and `b` | Decided 2026-10-30 |
19+| 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 |
20−| Local definitions | At the start of any body: a gate's, an arm's, a `^-`'s, a `~&`'s or a `++`'s | Decided 2026-10-30 |
20+| Spacing | Style, kept by the formatter: one or more spaces between items, and spaces allowed after an opener, before a closer and at the end of a line; faces, puns and typed path segments take no spaces; a rune is followed by one | Decided 2026-10-30 | Check |
21−| Value cycles | A non-gate value that depends on itself, even through a gate, is an error; mutually recursive gates are allowed | Decided 2026-10-30 |
21+| Path literals | `/posts/~zod` is an expression: `pathlit` is an operand | Decided 2026-10-30 | Check |
22−| Open molds | A mold's `[` and `(` may be left open at line end, one field or mold per deeper line; a `(` keeps the mold's name on its first line | Decided 2026-10-30 |
22+| Crash | `!!` is an operand, so `f !!` and `~[!!]` need no parentheses | Decided 2026-10-30 | Check |
23−| Open groups | A `(` alone at line end puts the call's head on the first deeper line | Decided 2026-10-30 |
23+| Sample names | Every bare name in a sample binds, at any depth: `\|= [a=@ b]` binds `a` and `b` | Decided 2026-10-30 | Check |
24−| Several open brackets | The deeper lines go to the last bracket, or the last rune's body, left open on a line, and the brackets before it close with it: `(column ~ ~[` needs no `)` | Decided 2026-10-30 |
24+| Local definitions | At the start of any body: a gate's, an arm's, a `^-`'s, a `~&`'s or a `++`'s | Decided 2026-10-30 | Check |
25−| Jibb code blocks | Labelled `jibb` in this doc; each is a golden test | Decided 2026-10-30 |
25+| Value cycles | A non-gate value that depends on itself, even through a gate, is an error; mutually recursive gates are allowed | Decided 2026-10-30 | Check |
26−| Definitions | `++` for values, `+$` for molds; no `=/` | Decided |
26+| Open molds | A mold's `[` and `(` may be left open at line end, one field or mold per deeper line; a `(` keeps the mold's name on its first line | Decided 2026-10-30 | Check |
27−| Unions | No `$?`: a `+$` with its cases on the lines below is a union, so every union written in Jibb has a name; one case is just that mold; a mold that isn't a union counts as a union of one case for tags and `\|=%tag`; a generic's `\|$` comes right after the `+$`'s name; tags anywhere; constructor heads and case disjointness compare literal noun values regardless of spelling, so `%$`, `%.y` and `~` are equal and overlapping cases are errors; cases differ as nouns, with `?` treated as the two atoms `%.y` and `%.n`, disjoint from cells and overlapping constants 0 and 1, and `!!` or any cell with an empty position disjoint from every case; a tag literal or `~` waits for its union, and an unresolved one is an error | Decided 2026-10-31 |
27+| Open groups | A `(` alone at line end puts the call's head on the first deeper line | Decided 2026-10-30 | Check |
28−| Printed unnamed unions | Print the cases separated by spaces, as `%approve %deny`; this is print-only, not Jibb syntax | Decided 2026-10-30 |
28+| Several open brackets | The deeper lines go to the last bracket, or the last rune's body, left open on a line, and the brackets before it close with it: `(column ~ ~[` needs no `)` | Decided 2026-10-30 | Check |
29−| Printed type constraints | Print an atom constraint as `$-([A A] A) where A is an atom`, an arithmetic atom constraint as `where A is an atom other than ?`, and a gate-free constraint as `$-([A A] ?) where A contains no gates`; separate multiple clauses with commas, as `where A is an atom, B contains no gates` | Decided 2026-10-31 |
29+| Jibb code blocks | Labelled `jibb` in this doc; each is a golden test | Decided 2026-10-30 | Check |
30−| Branching | `?-` only, loobeans included; exhaustive, with explicit catch-alls; covered arms are errors; failures say `!!` | Decided 2026-10-29 |
30+| Definitions | `++` for values, `+$` for molds; no `=/` | Decided | Yes |
31−| 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 |
31+| Unions | No `$?`: a `+$` with its cases on the lines below is a union, so every union written in Jibb has a name; one case is just that mold; a mold that isn't a union counts as a union of one case for tags and `\|=%tag`; a generic's `\|$` comes right after the `+$`'s name; tags anywhere; constructor heads and case disjointness compare literal noun values regardless of spelling, so `%$`, `%.y` and `~` are equal and overlapping cases are errors; cases differ as nouns, with `?` treated as the two atoms `%.y` and `%.n`, disjoint from cells and overlapping constants 0 and 1, and `!!` or any cell with an empty position disjoint from every case; a tag literal or `~` waits for its union, and an unresolved one is an error | Decided 2026-10-31 | No |
32−| Special rules | No built-ins; type-directed rules are welcome, each listed in the Grammar tab | Decided 2026-10-29 |
32+| Printed unnamed unions | Print the cases separated by spaces, as `%approve %deny`; this is print-only, not Jibb syntax | Decided 2026-10-30 | Check |
33−| 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 |
33+| Printed type constraints | Print an atom constraint as `$-([A A] A) where A is an atom`, an arithmetic atom constraint as `where A is an atom other than ?`, and a gate-free constraint as `$-([A A] ?) where A contains no gates`; separate multiple clauses with commas, as `where A is an atom, B contains no gates` | Decided 2026-10-31 | No |
34−| 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 |
34+| Branching | `?-` only, loobeans included; exhaustive, with explicit catch-alls; covered arms are errors; failures say `!!` | Decided 2026-10-29 | Yes |
35−| 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 |
35+| 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 |
36−| 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 |
36+| Special rules | No built-ins; type-directed rules are welcome, each listed in the Grammar tab | Decided 2026-10-29 | Yes |
37−| Mark names | Any name: `/%` names types after marks, and constructors poke with their type's mark; no alias marks | Decided 2026-10-26 |
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 |
38−| 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 |
38+| 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 |
39−| 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 |
39+| 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 |
40−| 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 |
40+| 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 |
41−| 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 |
41+| Mark names | Any name: `/%` names types after marks, and constructors poke with their type's mark; no alias marks | Decided 2026-10-26 | Yes |
42−| Layout | Indentation; juxtaposed calls; a bracket open at line end takes one item per line, with no closer | Decided |
42+| 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 |
43−| 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 |
43+| 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 |
44−| Long calls | One argument per line inside parentheses | Decided |
44+| 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−| 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 |
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 |
46−| Empty mold | `!!`, with no values; the expression has any type; pages are `(element !!)`, which keeps islands out of islands | Decided 2026-10-29 |
46+| 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 |
47−| 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 |
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 |
48−| 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 |
48+| 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 |
49−| 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 |
49+| Long calls | One argument per line inside parentheses | Decided | Yes |
50−| Loobean mold | `?`, switched with `?-` | Decided 2026-10-26 |
50+| 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 |
51−| Defaults | None | Decided |
51+| Empty mold | `!!`, with no values; the expression has any type; pages are `(element !!)`, which keeps islands out of islands | Decided 2026-10-29 | Yes |
52−| Modules | Records, not cores | Decided |
52+| 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 |
53−| 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 |
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 |
54−| Type identity | Recursive molds by name and module | Decided 2026-10-29 |
54+| 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 |
55−| Binding patterns | In `?-` arms; the last position binds the rest | Decided 2026-10-29 |
55+| Loobean mold | `?`, switched with `?-` | Decided 2026-10-26 | Yes |
56−| 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 |
56+| Defaults | None | Decided | Yes |
57−| 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 |
57+| Modules | Records, not cores | Decided | Yes |
58−| Loobean arithmetic | Arithmetic rejects loobean operands; comparison may accept them and returns `?` | Decided 2026-10-31 |
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 |
59−| Crashes | As in Hoon; an island keeps its model and shows the standard notice; a failing page, or one rendering a control outside an island, gets Jibb's error page; no render limit, so an endless render stalls the ship | Decided 2026-10-29 |
59+| Type identity | Recursive molds by name and module | Decided 2026-10-29 | Yes |
60−| Refinement types | None | Decided |
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 |
61−| Imports | `/-`, `/%` (a mark's type, with no face) and `/=`; no `/+`; cycles are errors | Decided 2026-10-29 |
61+| 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 |
62−| Hoon marks for Jibb types | None: wire types are the agent's marks, and Jibb's own types never cross | Decided 2026-10-26 |
62+| 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 |
63−| Core language | A small untyped core language between the checker and both backends: Nock's operations on nouns plus a lambda calculus with names; one sample per call; s-expressions as its text form; a reference interpreter in Hoon; three rules in its tab still proposed | Decided |
63+| Loobean arithmetic | Arithmetic rejects loobean operands; comparison may accept them and returns `?` | Decided 2026-10-31 | No |
64−| Stages | By kind: pages without data at commit, with data in the host, islands and stores in the browser; never inferred | Decided 2026-10-29 |
64+| Crashes | As in Hoon; an island keeps its model and shows the standard notice; a failing page, or one rendering a control outside an island, gets Jibb's error page; no render limit, so an endless render stalls the ship | Decided 2026-10-29 | Yes |
65−| Page loading | `load` maps route parameters, `~` for none, to one `ask` or `pure`; pages render per request from a fresh scry of the path, or of its case's scry path; nothing is watched or kept | Decided 2026-10-29 |
65+| Refinement types | None | Decided | Yes |
66−| Compile targets | Nock on the ship, JavaScript in the browser | Decided |
66+| Imports | `/-`, `/%` (a mark's type, with no face) and `/=`; no `/+`; cycles are errors | Decided 2026-10-29 | Yes |
67−| Optimizer | Basic lowering; holes later | Decided 2026-10-29 |
67+| Hoon marks for Jibb types | None: wire types are the agent's marks, and Jibb's own types never cross | Decided 2026-10-26 | Yes |
68−| Island `update` | In the browser; returns the model and a list of commands, which the runtime processes one at a time in list order | Decided 2026-11-02 |
68+| Core language | A small untyped core language between the checker and both backends: Nock's operations on nouns plus a lambda calculus with names; one sample per call; s-expressions as its text form; a reference interpreter in Hoon; three rules in its tab still proposed | Decided | Yes |
69−| Island `init` | Takes the page's data, returns the model | Decided 2026-10-29 |
69+| Stages | By kind: pages without data at commit, with data in the host, islands and stores in the browser; never inferred | Decided 2026-10-29 | Yes |
70−| Island rendering | `view` re-runs on model changes; a keyed diff patches the DOM; holes later | Decided 2026-10-29 |
70+| Page loading | `load` maps route parameters, `~` for none, to one `ask` or `pure`; pages render per request from a fresh scry of the path, or of its case's scry path; nothing is watched or kept | Decided 2026-10-29 | Yes |
71−| Data crossing to the browser | No gates in island data or models | Decided 2026-10-29 |
71+| Compile targets | Nock on the ship, JavaScript in the browser | Decided | Yes |
72−| Inputs | A message per input event, none mid-composition; controls reset to the latest view after every event; fields read-only until the island starts | Decided 2026-10-29 |
72+| Optimizer | Basic lowering; holes later | Decided 2026-10-29 | Yes |
73−| Transactions | None; one poke per command | Decided |
73+| Island `update` | In the browser; returns the model and a list of commands, which the runtime processes one at a time in list order | Decided 2026-11-02 | No |
74−| Reloads | Restart from the model the page is served with | Decided 2026-10-29 |
74+| Island `init` | Takes the page's data, returns the model | Decided 2026-10-29 | Yes |
75−| Shared state | Stores: browser agents written like API files, with `state`, a local `+$ poke` action mold and `(store init update)`; derived gates provide the generic `poke` command helper and state requests; one per page | Decided 2026-11-01 |
75+| Island rendering | `view` re-runs on model changes; a keyed diff patches the DOM; holes later | Decided 2026-10-29 | Yes |
76−| Store builder | `+$ store |$ [S] [init=S update=*]`, with `++ store |= [init=S update=$-([A S] S)] ^- (store S) [init update]`: the builder checks action `A`, while `main` exposes only state `S`; the store kind check verifies `A` against the poke declaration | Decided 2026-11-01 |
76+| Data crossing to the browser | No gates in island data or models | Decided 2026-10-29 | Yes |
77−| Subscriptions | By agent and path, shared per page; the first fact is full state, so no paths that need a scry path | Decided 2026-10-29 |
77+| Inputs | A message per input event, none mid-composition; controls reset to the latest view after every event; fields read-only until the island starts | Decided 2026-10-29 | Yes |
78−| Apps | One island under a catch-all route, given the path by `pure`; `%url` delivers the path on every change; in-section links act as `go`; focus moves to the first heading | Decided 2026-10-29 |
78+| Transactions | None; one poke per command | Decided | Yes |
79−| Layout vocabulary | Jibb's elements and theme tokens; the stylesheet comes from the theme alone; chars and fill are inline; `[%fill n]` below 1 counts as 1 | Decided 2026-10-29 |
79+| Reloads | Restart from the model the page is served with | Decided 2026-10-29 | Yes |
80−| Responsive layout | `stack` switches at the theme's `wide` | Decided 2026-10-29 |
80+| Shared state | Stores: browser agents written like API files, with `state`, a local `+$ poke` action mold and `(store init update)`; derived gates provide the generic `poke` command helper and state requests; one per page | Decided 2026-11-01 | No |
81−| Theme | A prelude mold with every token required: spaces, five tones with `normal` and `background`, language, zone, `wide`, and an optional static font; optional values such as dark tones use explicit backtick unit syntax; 4.5:1 contrast enforced | Decided 2026-11-01 |
81+| Store builder | `+$ store |$ [S] [init=S update=*]`, with `++ store |= [init=S update=$-([A S] S)] ^- (store S) [init update]`: the builder checks action `A`, while `main` exposes only state `S`; the store kind check verifies `A` against the poke declaration | Decided 2026-11-01 | No |
82−| Dark mode | Hand-written dark tones under `dark`, used when the reader prefers dark | Decided 2026-10-27 |
82+| Subscriptions | By agent and path, shared per page; the first fact is full state, so no paths that need a scry path | Decided 2026-10-29 | Yes |
83−| Links | All text escaped; in-app links are application paths, as `%/blog/(slug)`, with no query or fragment, checked at compile time against routes and static files; paths and unchecked `https`, `mailto` and `tel` URLs and root-relative cords such as `"/apps/groups"` have separate declarations; `link-unsafe`, `image-unsafe` and `go-unsafe` are the unchecked forms; both navigation declarations produce `[%go url=@t]`, with `go` converting the path to a cord including the app's base path; other cords render as text; a CSP on every page | Decided 2026-10-30 |
83+| Apps | One island under a catch-all route, given the path by `pure`; `%url` delivers the path on every change; in-section links act as `go`; focus moves to the first heading | Decided 2026-10-29 | Yes |
84−| Data layer | Hoon's nouns: units, treaps, loobeans | Decided |
84+| Layout vocabulary | Jibb's elements and theme tokens; the stylesheet comes from the theme alone; chars and fill are inline; `[%fill n]` below 1 counts as 1 | Decided 2026-10-29 | Yes |
85−| Prelude | Hoon's standard library regrouped: all names from the listed sections except explicitly excluded groups, including all of 3g, with Hoon's `tone` exposed as `tone.hoon` and Hoon's 1c `step` as `step.hoon`; arithmetic over aura variables, units, lists, maps, sets, queues, ordered maps, function helpers, text, atom printing, a zoned date printer, time and data molds; folds take a start; jetted functions have working Jibb implementations, whose shapes the compiler recognizes to use the Hoon versions, and may take gates; private helpers and low-level primitives live in a separate internal module imported without exposing them, with public foundational gates implemented in Jibb on those primitives; `clap` takes two units of the same type and a combining gate over that type; no signed or float gates, or parser gates outside 3g except `slav` and `slaw`; signed or float auras are errors | Decided 2026-10-30 |
85+| Responsive layout | `stack` switches at the theme's `wide` | Decided 2026-10-29 | Yes |
86−| `like` | The `(like A)` mold remains available; the value gate `like` maps the product of an existing `(like A)` with a gate `$-(A B)`, preserving the position and remaining input, and returns `(like B)` | Decided 2026-10-31 |
86+| Theme | A prelude mold with every token required: spaces, five tones with `normal` and `background`, language, zone, `wide`, and an optional static font; optional values such as dark tones use explicit backtick unit syntax; 4.5:1 contrast enforced | Decided 2026-11-01 | No |
87−| Wire format | Noun channels; Jibb's own noun codec in the browser | Decided 2026-10-29 |
87+| Dark mode | Hand-written dark tones under `dark`, used when the reader prefers dark | Decided 2026-10-27 | Yes |
88−| Hosting | One thin host agent on `%jibb` binds, caches and serves every Jibb desk; each desk vendors jibb-dev, names its base path in docket's `site+`, and builds and renders with its own copy through fixed entry points; install `%jibb` first; app agents stay plain Hoon; pokes only from the ship | Decided 2026-10-29 |
88+| Links | All text escaped; in-app links are application paths, as `%/blog/(slug)`, with no query or fragment, checked at compile time against routes and static files; paths and unchecked `https`, `mailto` and `tel` URLs and root-relative cords such as `"/apps/groups"` have separate declarations; `link-unsafe`, `image-unsafe` and `go-unsafe` are the unchecked forms; both navigation declarations produce `[%go url=@t]`, with `go` converting the path to a cord including the app's base path; other cords render as text; a CSP on every page | Decided 2026-10-30 | Check |
89−| Private pages | Served by the host per request and never cached; non-owners go to the login page | Decided 2026-10-29 |
89+| Data layer | Hoon's nouns: units, treaps, loobeans | Decided | Yes |
90−| Cache | Eyre holds only the hashed assets, all public; the host serves every page; a desk's entries are cleared on suspend or uninstall, and all by `-jibb!clear` | Decided 2026-10-29 |
90+| Prelude | Hoon's standard library regrouped: all names from the listed sections except explicitly excluded groups, including all of 3g, with Hoon's `tone` exposed as `tone.hoon` and Hoon's 1c `step` as `step.hoon`; arithmetic over aura variables, units, lists, maps, sets, queues, ordered maps, function helpers, text, atom printing, a zoned date printer, time and data molds; folds take a start; jetted functions have working Jibb implementations, whose shapes the compiler recognizes to use the Hoon versions, and may take gates; private helpers and low-level primitives live in a separate internal module imported without exposing them, with public foundational gates implemented in Jibb on those primitives; `clap` takes two units of the same type and a combining gate over that type; no signed or float gates, or parser gates outside 3g except `slav` and `slaw`; signed or float auras are errors | Decided 2026-10-30 | Check |
91−| Static files | Under `/ui/static/`, committed, at hashed immutable URLs; referenced by application path, so a missing file fails to compile, and images are sized from the file; no large media, since Clay keeps every version and the cache ignores `Range` | Decided 2026-10-29 |
91+| `like` | The `(like A)` mold remains available; the value gate `like` maps the product of an existing `(like A)` with a gate `$-(A B)`, preserving the position and remaining input, and returns `(like B)` | Decided 2026-10-31 | No |
92−| Routing | A literal beats a parameter, which beats a catch-all; parameters bind to `load`'s sample by name; `@ta` and `@tas` raw, other auras as Hoon prints them | Decided 2026-10-29 |
92+| Wire format | Noun channels; Jibb's own noun codec in the browser | Decided 2026-10-29 | Yes |
93−| Linking | Folder convention; the mark stores text; the host runs each desk's own compiler; modules cached by their own and their imports' hashes | Decided 2026-10-29 |
93+| Hosting | One thin host agent on `%jibb` binds, caches and serves every Jibb desk; each desk vendors jibb-dev, names its base path in docket's `site+`, and builds and renders with its own copy through fixed entry points; install `%jibb` first; app agents stay plain Hoon; pokes only from the ship | Decided 2026-10-29 | Yes |
94−| Access | Every page is private to the owner; public pages come in a later version | Decided 2026-10-29 |
94+| Private pages | Served by the host per request and never cached; non-owners go to the login page | Decided 2026-10-29 | Yes |
95−| 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 |
95+| Cache | Eyre holds only the hashed assets, all public; the host serves every page; a desk's entries are cleared on suspend or uninstall, and all by `-jibb!clear` | Decided 2026-10-29 | Yes |
96−| Editor support | Tree-sitter grammar | Decided |
96+| Static files | Under `/ui/static/`, committed, at hashed immutable URLs; referenced by application path, so a missing file fails to compile, and images are sized from the file; no large media, since Clay keeps every version and the cache ignores `Range` | Decided 2026-10-29 | Yes |
97−| Formatter | One canonical layout | Decided |
97+| Routing | A literal beats a parameter, which beats a catch-all; parameters bind to `load`'s sample by name; `@ta` and `@tas` raw, other auras as Hoon prints them | Decided 2026-10-29 | Yes |
98−| Name | Jibb | Decided |
98+| Linking | Folder convention; the mark stores text; the host runs each desk's own compiler; modules cached by their own and their imports' hashes | Decided 2026-10-29 | Yes |
99+| Access | Every page is private to the owner; public pages come in a later version | Decided 2026-10-29 | Yes |
100+| 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 |
101+| Editor support | Tree-sitter grammar | 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 |
103+| Name | Jibb | Decided | Yes |
104+
105+## Settled milestone 2 questions
106+
107+Kept only in this copy. These were open questions in [open-questions.md](../open-questions.md) until @iko settled them; the rows above record each choice, and the questions keep their numbers there, so references to them stay valid. Questions 3 and 32 are still open there.
108+
109+On 2026-10-30, @iko adopted gate-free `eq` arguments and map and set keys, treating gates as opaque when distinguishing union cases, and rejecting a non-gate value that depends on itself even through a gate. The checker infers and generalizes the gate-free constraint. @iko also said jetted prelude functions may take gates.
110+
111+**1. Settled: how the prelude identifies jetted functions.** On 2026-10-30, @iko said the prelude functions have working Jibb implementations, and the compiler recognizes their shapes and uses the Hoon versions so jets can fire.
112+
113+**2. Settled: how the prelude keeps helpers private.** On 2026-10-30, @iko chose a separate internal prelude module imported by the prelude, without exposing the imported helpers.
114+
115+**4. Settled: a capital in a local `++`.** On 2026-10-30, @iko said it shares the enclosing `++`'s variable of that name if the enclosing `++` also uses it; otherwise the local `++` introduces and generalizes its own variable. For example, `++ inner |= y=A y` shares `A` with an enclosing gate whose sample is `x=A`, but generalizes its own `A` if the enclosing `++` does not use `A`. A different type uses a different capital. The Grammar and Decisions record this alongside the earlier aura rules.
116+
117+**5. Settled: cells of no items or one.** On 2026-10-30, @iko said a single-item cell is the value and `[]` is an error. The theme's `dark=[tones=[…]]`, a record of one field, must still check.
118+
119+**6. Settled: a change with no items.** On 2026-10-30, @iko said `m()` is an error. The parser still accepts it; the checker needs to reject it and add a golden case.
120+
121+**7. Settled: the doc's blocks that aren't whole modules.** On 2026-10-30, @iko agreed to check each in its intended context: the `cmd` and `sub` definitions as prelude source, the Core language tab's `update` inside the todo island, and the Grammar's imports example against fixture files.
122+
123+**8. Settled: tuples and records.** On 2026-10-30, @iko agreed that an unnamed position can unify with a faced position and take its face; two different explicit faces still conflict. The Grammar and Decisions record this rule.
124+
125+**9. Settled: values where `*` is expected.** On 2026-10-30, @iko said `*` is the noun type, not a type variable; generic positions use proper type variables. A value already known to be `@ud` can be passed where `*` is expected. The `each` and `table` signatures use `key=K`.
126+
127+**10. Settled: navigation commands.** On 2026-10-30, @iko chose separate declarations for application paths and unchecked cords, with `link-unsafe`, `image-unsafe` and `go-unsafe` for the unchecked forms. `image-unsafe` takes a sized URL record. Both navigation declarations produce `[%go url=@t]`; `go` converts the application path to a cord including the app's base path.
128+
129+**11. Settled: stores and derived gates.** On 2026-11-01, @iko said a store's local `+$ poke` is an ordinary action mold and the runtime envelope is `raw-poke`; a derived name clashes with an import face; and an island watching a request whose case has a separate `scry=` path has a type error. The todo API's request is renamed `todo-by-id` so it does not clash with `/- todo`. The checker must account for the fact that a store's kind is determined by the type of `main`.
130+
131+**12. Settled: how to print a union without a name.** On 2026-10-30, @iko said to print its cases separated by spaces, as `%approve %deny`. This is print-only, not Jibb syntax.
132+
133+**13. Settled: how to print type constraints.** On 2026-10-30, @iko chose `$-([A A] A) where A is an atom` for an atom constraint and `$-([A A] ?) where A contains no gates` for a gate-free constraint. Multiple clauses are comma-separated, as `where A is an atom, B contains no gates`.
134+
135+**14. Settled: how the prelude implements foundational operations.** On 2026-10-30, @iko chose private low-level primitives in the internal prelude module, with the public foundational gates implemented in Jibb on top of them.
136+
137+**15. Settled: unrestricted atoms and shared auras.** On 2026-10-30, @iko said `@` means any atom, independently at each occurrence, so Hoon `dime` and `pint` keep their bare-`@` fields. A specific atom such as `@ud` fits where `@` is expected; an `@` value needs a check to fit `@ud`. Shared atom types use one capital, with the atom constraint inferred from its body, as for `add` taking `[A A]` and returning `A`.
138+
139+**16. Settled: loobeans in union disjointness.** On 2026-10-30, @iko said `?` counts as its two atoms, `%.y` and `%.n`: it is disjoint from any cell and overlaps the constants 0 and 1.
140+
141+**17. Settled: empty cases in union disjointness.** On 2026-10-30, @iko said `!!` is disjoint from every case. A cell containing an empty position at any depth is itself empty and is also disjoint from every case.
142+
143+**18. Settled: the value gate `like`.** On 2026-10-31, @iko chose a gate `(like convert result)` that maps the product of an existing `(like A)` result with `convert=$-(A B)`, yielding `(like B)` while preserving its position and remaining input. An absent result stays absent. The `(like A)` mold remains available in the separate mold namespace. Hoon's wet `+like` instead builds a gate that constructs a result from an input noun; the chosen Jibb value gate is an adaptation of that behavior.
144+
145+**19. Settled: Hoon aura families and `step.hoon`.** On 2026-10-30, @iko chose `step.hoon` for Hoon 1c `step`, avoiding a clash with the Grammar example's `step`, and chose one-way widening across Hoon aura families: for example, `@ud` and `@ux` fit `@u`, and `@tD` fits `@t`. The reverse needs a check. The `step.hoon` group representation is not implemented yet.
146+
147+**20. Settled: the type of `clap`.** On 2026-10-30, @iko chose one shared value type for both units and the combining gate. If either unit is absent, `clap` returns the other; if both are present, it applies the gate to their values and wraps the result.
148+
149+**21. Settled: duplicate faces in imported Hoon records.** On 2026-10-30, @iko chose to reject an imported Hoon record with duplicate field names where its type is used. Hoon permits `[a=@ud a=@t]` and picks the first `a`; Jibb rejects it.
150+
151+**22. Settled: overlapping imported `$%` and `$?` cases.** On 2026-10-30, @iko confirmed that the general union disjointness rule rejects imported `$%` and `$?` cases that overlap as nouns where the type is used, as it does for `$^`. The importer rejects recognizable overlaps and fails closed when it cannot verify them.
152+
153+**23. Settled: converging explicit capitals.** On 2026-10-30, @iko chose that a body cannot force two separately written capitals to be equal. For `++ repeated |= x=(choice A A) x`, `++ f |= x=(choice A B) (repeated x)` is an error; use `A` in both positions when the type must be shared. This also applies across local captures and within generic mold applications.
154+
155+**24. Settled: how the internal prelude provides `raw-poke`.** On 2026-11-01, @iko chose to define `raw-poke` in the source-backed private internal prelude module and re-export it through the public prelude as an ordinary transparent type. Ordinary modules can construct and inspect its values, while derived API/store `poke` helpers return commands. This settles `raw-poke`; it does not decide the representation of `ask` or `qath`.
156+
157+**25. Settled: how the prelude provides `ask` and `qath`.** On 2026-10-31, @iko chose ordinary transparent types defined in the internal prelude and re-exported normally, as for `raw-poke`. Callers may construct and inspect their values.
158+
159+**26. Settled: the `step` example's `at` binder.** On 2026-10-31, @iko chose to rename the `describe` pattern binder to `sent-at`, keeping Hoon's `at` in the prelude and the no-shadowing rule.
160+
161+**27. Settled: duplicate fields in a Jibb-written record.** On 2026-10-31, @iko chose to reject duplicate field names, as for imported Hoon records.
162+
163+**28. Settled: arithmetic on loobeans.** On 2026-10-31, @iko chose to reject loobean operands for arithmetic. Comparison may still accept loobeans and returns `?`. The checker needs to retain this constraint through inference, generalization and instantiation before it exports `add` or `dec`.
164+
165+**29. Settled: printing the arithmetic atom constraint.** On 2026-10-31, @iko chose `where A is an atom other than ?` for a generic arithmetic type whose atom variable excludes loobeans.
166+
167+**30. Settled: a hole inferred as a generic variable.** On 2026-10-31, @iko said a hole resolved to an explicitly written type variable counts as inferred: in `++ id |= x=A ^- _ x`, the result hole is `A`. Named molds must determine their own holes without constraints from later uses; an unconstrained hole is an error.
168+
169+**31. Settled: uses of a value with a hole.** On 2026-10-31, @iko said a value definition must determine its own holes; another definition's use cannot fix an otherwise unresolved hole. For example, `++ id |= x=_ x` remains an error even if a later definition calls `id` with a cord.
170+
171+**33. Settled: watching a request with unknown provenance.** On 2026-10-31, @iko said an island may watch a request only if the checker proves it watchable at compile time. An unknown request, including one built or passed through a gate without sufficient evidence, is rejected rather than deferred to a runtime check.
172+
173+**34. Settled: constructors and equal noun literals.** On 2026-10-31, @iko said expressions with the same runtime representation count as equal, and cases that cannot be distinguished at runtime are rejected at compile time. Thus `|=%$` matches a case headed by `%$`, `%.y` or `~`: each is the noun 0. Cases with equal heads and overlapping payloads cannot coexist in a union.
174+
175+Review question 25, when to build `eq` and the gate-free constraint, is settled: @iko's commit 0858191 adds `eq` and infers the constraint.
99
176
100## Checked against the kernel
177## Checked against the kernel
101
178
docs/spec/grammar.md+55−34
@@ -6,19 +6,20 @@ The syntax the compiler accepts.
6
6
7## Lexical rules
7## Lexical rules
8
8
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.
10- **Layout tokens**: a deeper line emits INDENT, the same depth NEWLINE, a shallower one a DEDENT per closed level, then NEWLINE.
10- **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.
12- **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)`.
12- **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.
14- **Comments**: `::` to the end of the line, outside strings; inside a string, `::` is text.
14- **Comments**: `::` to the end of the line, outside strings; inside a string, `::` is text.
15- **Names**: Hoon terms; lowercase letters, digits and hyphens, starting with a letter.
15- **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.
16
17
17## Literals
18## Literals
18
19
19| Form | Example | Type |
20| Form | Example | Type |
20| --- | --- | --- |
21| --- | --- | --- |
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 |
22| Hexadecimal | `0x1f` | `@ux` |
23| Hexadecimal | `0x1f` | `@ux` |
23| Base 32 | `0v5.fdf99` | `@uv` |
24| Base 32 | `0v5.fdf99` | `@uv` |
24| Ship | `~zod`, `~sampel-palnet` | `@p` |
25| Ship | `~zod`, `~sampel-palnet` | `@p` |
@@ -42,27 +43,35 @@ Every literal reads exactly as Hoon reads it: `1000` is an error (write `1.000`)
42
43
43- **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.
44- **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.
44- **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- **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.
46- **Pairs and units**: `gap+%s2` and `` `x `` bind tighter than calls, so `pad+%s3 gap+%s2` is two items.
47- **Pairs and units**: `gap+%s2` and `` `x `` bind tighter than calls, so `pad+%s3 gap+%s2` is two items.
47- **Wing** `title.p`, also for imports and prelude groups, which are records: `card.card`, `space.theme.theme`, `get.by`. **Change** `m(draft="x" error=~)`.
48- **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.
48- **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`.
50- **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`.
49- **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.
51- **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.
50- **No operators**: `eq a b`, `not x`, `gth a b` are gates.
52- **No operators**: `eq a b`, `not x`, `gth a b` are gates.
51
53
52## Runes
54## Runes
53
55
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.
55
57
56- `++` **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.
58- `++` **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.
57- `+$` **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.
59- `+$` **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.
58- `|=` **bartis**: a gate with a faced sample, `m=model`, `=msg` (`msg=msg`) or `[a=@ b=@]`; the body on the same line or below.
60- `|=` **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`.
60- `^-` **kethep**: a cast; the mold on its line, the expression after it or below.
62- `^-` **kethep**: a cast; the mold on its line, the expression after it or below.
61- `~&` **sigpam**: prints the value on its line, then runs the body below; output goes to the ship's log or the browser's console.
63- `~&` **sigpam**: prints the value on its line, then runs the body below; output goes to the ship's log or the browser's console.
62- `!!` **zapzap**: a crash, an expression of any type; as a mold, the empty mold. It is an operand, so `f !!` and `~[!!]` need no parentheses.
64- `!!` **zapzap**: a crash, an expression of any type; as a mold, the empty mold. It is an operand, so `f !!` and `~[!!]` need no parentheses.
63- `$-` **buchep**: a gate's mold, `$-(sample product)`.
65- `$-` **buchep**: a gate's mold, `$-(sample product)`.
64- `|$` **barbuc**: a generic mold, right after a `+$`'s name: `+$ result |$ [V E]`, then the mold on its line or the cases below.
66- `|$` **barbuc**: a generic mold, right after a `+$`'s name: `+$ result |$ [V E]`, then the mold on its line or the cases below.
65
67
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+
66Only `|=` and `$-` have wide forms: `|=(sample expr)` and `$-(mold mold)`. Their children are operands, so calls inside need parentheses.
75Only `|=` and `$-` have wide forms: `|=(sample expr)` and `$-(mold mold)`. Their children are operands, so calls inside need parentheses.
67
76
68Left out on purpose:
77Left out on purpose:
@@ -98,9 +107,9 @@ An imported Hoon record with duplicate field names is an error where used; impor
98A file is a module: imports, then definitions.
107A file is a module: imports, then definitions.
99
108
100- `+$ name mold` defines a mold; `++ name expr` a value.
109- `+$ 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.
102- 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.
111- 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.
104- 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.
113- 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.
105- 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.
114- 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.
106
115
@@ -121,15 +130,16 @@ Every other name is free.
121A 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.
130A 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.
122
131
123- **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.
132- **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 `?`.
125- **Constants**: `%add`, `~` and the loobeans have one value each.
134- **Constants**: `%add`, `~` and the loobeans have one value each.
126- **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.
135- **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.
127- **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.
136- **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.
128- **Containers**: `(list A)`, `(unit A)`, `(set A)`, `(map K V)`, `(mop K V)`, `(qeu A)`, `(jar K V)`, `(jug K V)`.
137- **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)])`.
130- **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.
140- **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.
131- **Generic molds**: `+$ result |$ [V E]` with cases below; `|$` goes only right after a `+$`'s name.
141- **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**: `!!`.
133- **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.
143- **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.
134- **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`.
144- **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`.
135- **Identity**: recursive molds go by name and module.
145- **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
144- `|=%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.
154- `|=%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.
145- 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.
155- 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.
146- 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)`.
156- 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.
148- Patterns need none of this; they're checked against the subject's type.
158- Patterns need none of this; they're checked against the subject's type.
149
159
150```jibb
160```jibb
@@ -159,12 +169,12 @@ A tag literal or `~` gets a fresh type variable and a pending constraint: the va
159
169
160## Literals by context
170## Literals by context
161
171
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`.
163
173
164| Literal | Can become | Default |
174| Literal | Can become | Default |
165| --- | --- | --- |
175| --- | --- | --- |
166| Tag `%a`, or `~` | A union's case or a constant atom | None: an error asking for a `^-` |
176| 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` |
168| Cell `[x xs]` | A tuple, a record, a cons | A tuple |
178| Cell `[x xs]` | A tuple, a record, a cons | A tuple |
169
179
170- 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.
180- 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
181
191
182## Patterns
192## Patterns
183
193
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`.
185
195
186| Pattern | Matches | Binds |
196| Pattern | Matches | Binds |
187| --- | --- | --- |
197| --- | --- | --- |
@@ -192,11 +202,15 @@ Arms are tried in order. Every case needs an arm or a catch-all, `*` or a bare n
192| `[%move %left n]` | Tagged `%move`, then `%left` | `n` |
202| `[%move %left n]` | Tagged `%move`, then `%left` | `n` |
193| `~` | Null | Nothing |
203| `~` | Null | Nothing |
194| `[~ x]` | A unit holding a value | `x` |
204| `[~ 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` |
195| `1.000`, `"milk"`, `~zod` | That literal | Nothing |
207| `1.000`, `"milk"`, `~zod` | That literal | Nothing |
196| `[a b]` | Any cell; `b` is the rest | `a`, `b` |
208| `[a b]` | Any cell; `b` is the rest | `a`, `b` |
197| `*` | Anything | Nothing |
209| `*` | Anything | Nothing |
198| `x` | Anything | `x` |
210| `x` | Anything | `x` |
199
211
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+
200Tags can sit anywhere in a case, and a case can carry several:
214Tags can sit anywhere in a case, and a case can carry several:
201
215
202```jibb
216```jibb
@@ -209,11 +223,11 @@ Tags can sit anywhere in a case, and a case can carry several:
209
223
210++ describe |= s=step
224++ describe |= s=step
211 ?- s
225 ?- s
212− [%move %left n] "left {n}"
226+ [%move %left n] "left {n}"
213− [%move %right n] "right {n}"
227+ [%move %right n] "right {n}"
214− [t %draft] t
228+ [t %draft] t
215− [t %sent sent-at] t
229+ [t %sent sent-at] t
216− %stop "stop"
230+ %stop "stop"
217```
231```
218
232
219Leaving out `%stop` is an error naming it; to crash instead, write `%stop !!`.
233Leaving out `%stop` is an error naming it; to crash instead, write `%stop !!`.
@@ -235,14 +249,21 @@ definition = "+$" name [ generic ] ( mold | cases )
235generic = "|$" "[" typevar { typevar } "]" ;
249generic = "|$" "[" typevar { typevar } "]" ;
236cases = INDENT mold { NEWLINE mold } DEDENT ; (* one case is that mold; more make a union *)
250cases = INDENT mold { NEWLINE mold } DEDENT ; (* one case is that mold; more make a union *)
237
251
252+body = INDENT rest DEDENT ;
238−body = INDENT { definition NEWLINE } expr 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 *)
239expr = rune | call ;
258expr = rune | call ;
240call = operand { operand } ;
259call = operand { operand } ;
241operand = literal | qath | ref | change | pair | unit | group | list | tuple
260operand = literal | qath | ref | change | pair | unit | group | list | tuple
242 | gate | ctor | pathlit | "!!" ;
261 | gate | ctor | pathlit | "!!" ;
243ref = wing ;
262ref = wing ;
244wing = name { "." name } ;
263wing = 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 ;
246pair = name "+" operand ; (* [%name operand] *)
267pair = name "+" operand ; (* [%name operand] *)
247unit = "`" operand ; (* [~ operand] *)
268unit = "`" operand ; (* [~ operand] *)
248group = "(" expr ")" | "(" { operand } open ;
269group = "(" expr ")" | "(" { operand } open ;
@@ -274,7 +295,7 @@ pathmold = "/" [ segment { "/" segment } ] ;
274segment = knot | "[" name "=" ( aura | "_" ) "]" ;
295segment = knot | "[" name "=" ( aura | "_" ) "]" ;
275
296
276pattern = term | number | string | ship | loobean | "~" | "*" | name
297pattern = 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 *)
278
299
279literal = number | string | ship | date | duration | knotlit
300literal = number | string | ship | date | duration | knotlit
280 | term | loobean | "~" ;
301 | term | loobean | "~" ;
@@ -283,7 +304,7 @@ pathlit = "/" knot { "/" knot } ;
283term = "%" name | "%" decimal | "%&" | "%|" | "%$" ;
304term = "%" name | "%" decimal | "%&" | "%|" | "%$" ;
284loobean = "%.y" | "%.n" ;
305loobean = "%.y" | "%.n" ;
285aura = "@" { lower } [ upper ] ;
306aura = "@" { lower } [ upper ] ;
286−typevar = upper ;
307+typevar = upper { lower | digit } ;
287name = lower { lower | digit | "-" } ;
308name = lower { lower | digit | "-" } ;
288knot = { lower | digit | "-" | "." | "~" | "_" } ;
309knot = { lower | digit | "-" | "." | "~" | "_" } ;
289```
310```
@@ -298,11 +319,11 @@ knot = { lower | digit | "-" | "." | "~" | "_" } ;
298 %toggle
319 %toggle
299
320
300++ main (store init update)
321++ main (store init update)
301−++ init ^- state [~ %.n]
322+++ init ^- state [items=~ open=%.n]
302++ update |= [a=poke s=state]
323++ update |= [a=poke s=state]
303 ?- a
324 ?- a
304− [%add item] s(items=[item items.s])
325+ [%add item] s(items=[item items.s])
305− %toggle s(open=(not open.s))
326+ %toggle s(open=(not open.s))
306```
327```
307
328
308```jibb
329```jibb
@@ -320,15 +341,15 @@ knot = { lower | digit | "-" | "." | "~" | "_" } ;
320 [%acked err=(unit @t)]
341 [%acked err=(unit @t)]
321
342
322++ init |= ~
343++ init |= ~
323− [[~ %.n] ""]
344+ [cart=[items=~ open=%.n] note=""]
324
345
325++ update |= [=msg m=model]
346++ update |= [=msg m=model]
326 ?- msg
347 ?- msg
327− [%noted t] [m(note=t) ~]
348+ [%noted t] [m(note=t) ~]
328− %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
349+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
329− %toggle [m ~[(poke.cart %toggle |=%acked)]]
350+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
330− [%got c] [m(cart=c) ~]
351+ [%got c] [m(cart=c) ~]
331− [%acked err] [m ~]
352+ [%acked err] [m ~]
332
353
333++ subs |= m=model
354++ subs |= m=model
334 ~[[%watch (state.cart |=%got)]]
355 ~[[%watch (state.cart |=%got)]]
docs/spec/overview.md+9−9
@@ -465,18 +465,18 @@ A `page`: each request scries `%blog` and renders in Nock.
465 [%acked err=(unit @t)]
465 [%acked err=(unit @t)]
466
466
467++ init |= ts=(list item.todo)
467++ init |= ts=(list item.todo)
468− [ts "" ~]
468+ [todos=ts draft="" error=~]
469
469
470++ update |= [=msg m=model]
470++ update |= [=msg m=model]
471 ?- msg
471 ?- msg
472− [%typed t]
472+ [%typed t]
473− ?- (gth (lent (tuba (trip t))) 80)
473+ ?- (gth (lent (tuba (trip t))) 80)
474− %.y [m(draft=t error=`"Too long") ~]
474+ %.y [m(draft=t error=`"Too long") ~]
475− %.n [m(draft=t error=~) ~]
475+ %.n [m(draft=t error=~) ~]
476− %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
476+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
477− [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
477+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
478− [%got ts] [m(todos=ts) ~]
478+ [%got ts] [m(todos=ts) ~]
479− [%acked err] [m(error=err) ~]
479+ [%acked err] [m(error=err) ~]
480
480
481++ subs |= m=model
481++ subs |= m=model
482 ~[[%watch (todos.todo |=%got)]]
482 ~[[%watch (todos.todo |=%got)]]
docs/status.md+268−282
@@ -1,11 +1,13 @@
1# Status
1# Status
2
2
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
4
6
5| # | Milestone | Status |
7| # | Milestone | Status |
6| --- | --- | --- |
8| --- | --- | --- |
7| 1 | Parser and mark | Done (7c739b7; the doc's grammar decisions of 2026-10-30 in ab797a9) |
9| 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) |
9| 3 | Core language | Not started |
11| 3 | Core language | Not started |
10| 4 | Host and static pages: the first release | Not started |
12| 4 | Host and static pages: the first release | Not started |
11| 5 | Published pages | Not started |
13| 5 | Published pages | Not started |
@@ -13,293 +15,277 @@ As of 2026-11-02. The plan is [spec/implementation-plan.md](spec/implementation-
13| 7 | Tooling | Not started |
15| 7 | Tooling | Not started |
14| 8 | Polish | Not started |
16| 8 | Polish | Not started |
15
17
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.
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.
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. `tools/type-union-source-test` exercises the source and state bounds and failure paths under eval and on the ship. 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. `tools/type-deferred-prepared-test` checks the exact recovered types and unchanged `partial inference; module not checked` disclaimer under eval and on the ship. List-literal deferral and import-aware recovery remain unsupported.
35−
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 whose transparent tuple body ends in null when update, view and subs are already resolved. It derives the expected gate through the ordinary positional program fit with fresh IDs and stable replay, then re-infers the actual initializer and `main` under all ordinary finalization and kind checks. Non-main libraries, aliases, nonempty or 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 checks a call-bodied annotated initializer outside the tuple recovery shape 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−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.
65−
66−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.
67−
68−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.
69−
70−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.
71
19
72−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.
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.
73
21
74−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.
22+## Reading the tables
75
23
76−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.
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)).
77
27
78−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.
28+## Parser and mark
79
29
80−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.
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`.
81
31
82−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.
32+| Area | Status | Proved by |
83−
33+| --- | --- | --- |
84−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.
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` |
85−
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` |
86−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.
36+| Layout pass: `+layout` (library section 2) emits INDENT, DEDENT and NEWLINE | Done | `lex-layout-*`, `lex-indent-*`, `lex-rune-layout-*` |
87−
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-*` |
88−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.
38+| Parser: `+parse` and `+parse-tokens` (library section 3) turn the Grammar tab's EBNF into a syntax tree | Done | every golden `tree.txt` |
89−
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/) |
90−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.
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-*` |
91−
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-*` |
92−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.
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` |
93−
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` |
94−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.
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/) |
95−
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-*` |
96−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.
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` |
97−
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` |
98−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.
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/) |
99−
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 |
100−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.
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/) |
101−
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/) |
102−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.
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 |
103−
53+
104−## Milestone 1: parser and mark
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.
105−
55+
106−What the plan asks for, and where it is:
56+## Types and prelude: full-module checks
107−
57+
108−| The plan | Where |
58+| Area | Status | Proved by |
109−| --- | --- |
59+| --- | --- | --- |
110−| The `%jibb` mark as the first tab gives it | `jibb-dev/mar/jibb.hoon`, as the doc writes it |
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) |
111−| The layout pass, emitting INDENT, DEDENT and NEWLINE | `+layout` in `jibb-dev/lib/jibb.hoon`, designed in its section 2 |
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) |
112−| 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 |
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) |
113−| 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) |
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) |
114−| 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 |
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) |
115−| 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) |
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) |
116−| 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 |
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) |
117−
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) |
118−Besides the plan's list:
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) |
119−
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) |
120−- 660 golden cases: 440 that parse and 220 that fail, each failure at a stated line and column. One failing case has an unclear expectation (corpus question 3). The newer type-output cases exercise only the partial inference fragment. Each case's `about.txt` quotes the doc's words it tests.
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) |
121−- The 660-case corpus passed under `urbit eval` in 108.0 s while other checks were running. The fake ship passed all 717 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.
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) |
122−- `tools/testdata/selftest` (22 checks), `tools/testdata/ship-selftest` and `tools/testdata/clay-fixtures-selftest` test the tools themselves; the last checks temporary Clay fixture cleanup and signal handling without a ship.
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) |
123−- 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.
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) |
124−- Speed: starting `urbit eval` and building the library takes about 8 s. After that, a 2,000-line module of 400 definitions parses in about a second. Loops over definitions, arms, lines and items grow no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (library section 3).
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) |
125−
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) |
126−### History
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/) |
127−
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/) |
128−| Commit | Date | What |
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: does not establish complete shadowing coverage | [jibb-module-scope](../tests/lib/jibb-module-scope.hoon), [types-prelude-interface](../tests/golden/types-prelude-interface/) |
213+| `fall` and `need` | Done | [prelude-list-unit](../tests/golden/prelude-list-unit/), [types-prelude-direct](../tests/golden/types-prelude-direct/) |
214+| `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/) |
215+| `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/) |
216+| `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/) |
217+| `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/) |
218+| `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/) |
219+| `lent` | Done | [types-prelude-lent](../tests/golden/types-prelude-lent/) |
220+| `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) |
221+| `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) |
222+| `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) |
223+| `lth`, `gte` and `lte` over `gth` and `not` | Partial: complete import checking is unfinished | [types-prelude-comparison](../tests/golden/types-prelude-comparison/) |
224+| 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) |
225+| `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/) |
226+| `cmd`, the doc's generic union with five cases | Partial: the prelude inventory is incomplete | [types-prelude-cmd](../tests/golden/types-prelude-cmd/) |
227+| `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) |
228+| `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/) |
229+| `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/) |
230+| `raw-poke`, defined in the internal prelude and re-exported as a transparent type | Done | [jibb-poke-bridge](../tests/lib/jibb-poke-bridge.hoon) |
231+| 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/) |
232+| `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) |
233+| 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/) |
234+| `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/) |
235+| 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/) |
236+| `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/) |
237+| Execution and jet recognition of prelude gates and primitives | Missing | none |
238+
239+## Types and prelude: Hoon importer
240+
241+| Area | Status | Proved by |
242+| --- | --- | --- |
243+| 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) |
244+| 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) |
245+| 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) |
246+| 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) |
247+| 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/) |
248+| 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) |
249+| 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) |
250+| 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) |
251+| 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) |
252+| 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) |
253+| `$?` 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) |
254+| 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) |
255+| `$~` 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) |
256+| 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) |
257+| 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) |
258+| 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) |
259+| The importer golden: 221 projections | Done | [jibb-import](../tests/lib/jibb-import.hoon), [importer/tree.txt](../tests/importer/tree.txt) |
260+| 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/) |
261+
262+## Desks and tools
263+
264+| Area | Status | Proved by |
129| --- | --- | --- |
265| --- | --- | --- |
130−| 1cb51df | 2026-10-29 | Foundation: the parser's design, the tools, the desks, the vendored base-dev and landscape files, the golden corpus |
266+| `tools/golden`: the golden corpus under `urbit eval` | Done | `tools/testdata/selftest` |
131−| 15a5545 | 2026-10-29 | The layout pass |
267+| `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` |
132−| 3c5f50a | 2026-10-29 | The parser |
268+| `tools/ship test`: the same arms and one arm per golden case on the fake ship, 753 in all | Done | `tools/testdata/ship-selftest` |
133−| 7c739b7 | 2026-10-30 | Fixes from two independent audits; milestone 1 done |
269+| `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 |
134−| 5a4aa73 | 2026-10-30 | `tools/doc-blocks`, after the doc labelled its Jibb blocks |
270+| `nix build` and `nix flake check`: the four desks, and every check in the Nix sandbox | Done | [flake.nix](../flake.nix) |
135−| ab797a9 | 2026-10-30 | The 12 grammar decisions of 2026-10-30: four changed the parser, eight confirmed it |
271+| The tools' own tests: `tools/testdata/selftest` (23 checks) and `tools/testdata/ship-selftest` | Done | the two scripts |
136−| aad6ddb | 2026-10-30 | Drop `$?`; `+$` takes union cases below its name |
272+| `tools/hoon --no-debug` builds the library without `!:`, for timings | Done | `tools/testdata/selftest` |
137−| 1dd92a6 | 2026-10-30 | Begin type inference and Hoon imports |
273+| A UI runtime and the shared host | Missing: the `jibb` desk holds only `desk.bill` and `sys.kelvin` | none |
138−| 51ce4d9 | 2026-10-30 | Extend partial inference and importer, record type and prelude decisions |
274+
139−| be6d2a5 | 2026-10-30 | Add atom widening, nested collections and case-local Hoon import fixtures |
275+## Gaps
140−| 26554ac | 2026-10-30 | Infer an atom constraint, extend the prelude and read example molds through Clay |
276+
141−| fbeaa83 | 2026-10-30 | Extend atom constraints and nested ordered-map imports; connect Clay types to partial inference |
277+- 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)).
142−| 47a1f49 | 2026-10-30 | Read validated Ford imports, widen aura families, and show both sites of selected errors |
278+- 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/)).
143−| bd37989 | 2026-10-30 | Read mark samples and test partial mark imports; reject unproven nested `$^`; preserve atom constraints through aliases |
279+- 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.
144−| 2d5deb2 | 2026-10-30 | Default gate-free decimal types, validate named Hoon mold lookup, and isolate fixture failures |
280+- 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/)).
145−| 1b7dbae | 2026-10-30 | Infer acyclic local definitions and parse case-local Jibb module fixtures |
281+- 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).
146−| 8b9c9ac | 2026-10-30 | Preserve recursive import origins, infer simple local molds, and supply Jibb module sources to the partial checker |
282+- 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)).
147−| 529736a | 2026-10-30 | Infer supported library import graphs and guard nested Hoon `$^` in collections |
283+- 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.
148−| 8bf1b12 | 2026-10-30 | Infer selected record faces and check nested `$^` in static Hoon records |
284+- 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)).
149−| d8ac47d | 2026-10-30 | Cache library interfaces, preserve imported Hoon record faces, and check nested tagged unions |
285+- 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)).
150−| edd9277 | 2026-10-30 | Infer nonrecursive generic mold aliases with lexical parameters |
286+- 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)).
151−| 4406f6f | 2026-10-30 | Resolve selected contextual tags and check explicit imported unions |
287+- 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.
152−| 5c73614 | 2026-10-30 | Print supported named and escaping union types |
153−| 0070584 | 2026-10-30 | Propagate union context through loobean branches, read selected unions in Hoon collections, and add `flit` |
154−| 250564c | 2026-10-30 | Infer selected named generic unions, test Hoon collection wrappers, and add list helpers |
155−| e95ef8f | 2026-10-30 | Bridge selected Hoon unions into partial inference and support generic union aliases |
156−| 56a899f | 2026-10-30 | Infer matching variable types in faced fields and bridge opaque Hoon collections |
157−| 4d45d2f | 2026-10-30 | Resolve selected contextual null literals |
158−| e878edc | 2026-10-30 | Infer complete unit-shaped branches and bridge selected recursive Hoon molds |
159−| 743dfd8 | 2026-10-30 | Propagate union context through unit-shaped branches |
160−| 3f90fa8 | 2026-10-30 | Share a partial prelude interface across module inference |
161−| 29bd39f | 2026-10-30 | Infer contextual list literals and validate prelude parity |
162−| a2a6ef5 | 2026-10-30 | Infer complete list-shaped branches |
163−| 671fe72 | 2026-10-30 | Infer contextual list nulls and cons cells |
164−| 7e69436 | 2026-10-30 | Infer selected self-recursive gates |
165−| 9ab52e8 | 2026-10-30 | Infer recursive branches with closed base types |
166−| d782b45 | 2026-10-30 | Propagate list context and apply settled type decisions |
167−| c7082e0 | 2026-10-30 | Infer multi-argument calls |
168−| 918acbd | 2026-10-30 | Infer recursive gates from their samples first |
169−| 1470d18 | 2026-10-30 | Infer selected prelude list helpers |
170−| 10cbf9c | 2026-10-30 | Infer selected local recursive gates and distinguish reader diagnostics |
171−| 45afb13 | 2026-10-30 | Infer local capital scopes and report direct reader diagnostics |
172−| 054e651 | 2026-10-30 | Report nested reader diagnostics |
173−| 98c19cd | 2026-10-30 | Infer known-aura string interpolation |
174−| ddba633 | 2026-10-30 | Infer top-level mutually recursive gates |
175−| 9f1517e | 2026-10-30 | Infer whole-case union patterns and prelude `turn` |
176−| 9dd35c8 | 2026-10-31 | Match finite boolean refinements of union cases |
177−| 54852d4 | 2026-10-31 | Contextualize tuple calls and infer known record changes |
178−| 0bc5113 | 2026-10-31 | Contextualize record initializers and infer unit construction |
179−| 264a436 | 2026-10-31 | Contextualize unit payloads in casts, calls and nested values |
180−| a140383 | 2026-10-31 | Report missing union tags and infer prelude unit helpers |
181−| d69cc52 | 2026-10-31 | Infer longer cell binder patterns and prelude unit helpers |
182−| ae35005 | 2026-10-31 | Import source-verified tagged Hoon unions |
183−| c8f894a | 2026-10-31 | Report nested missing tags and contextualize union branch results |
184−| ef2ea71 | 2026-10-31 | Import Hoon null singleton cases |
185−| 67f900e | 2026-10-31 | Infer local mutual gates and uncontextualized lists |
186−| 7ff15f1 | 2026-10-31 | Contextualize finite union patterns and record the initial poke decision |
187−| c790a9f | 2026-10-31 | Expose transparent `poke` from the internal prelude |
188−| ef4772a | 2026-10-31 | Bridge imported loobeans and loobean singletons |
189−| ad46655 | 2026-10-31 | Bridge selected imported any-noun molds |
190−| beada10 | 2026-10-31 | Import source-proved Ford mark unions, analyze API paths and infer list helpers |
191−| e28f7be | 2026-10-31 | Diagnose proven non-gate cycles and import Tlon null-payload union cases |
192−| fd2f288 | 2026-10-31 | Infer qualified fields of imported values |
193−| ed9291e | 2026-10-31 | Infer term-headed pairs and function helpers, and import nested named unions |
194−| ad0265e | 2026-10-31 | Infer proven single-case patterns and the prelude command union |
195−| 413b12b | 2026-10-31 | Propagate known result context into generic calls and batch ship deletions |
196−| c690076 | 2026-10-31 | Propagate loobean context, infer predicate helpers, and import named ordered-map operands |
197−| 0bf6178 | 2026-10-31 | Bridge recursive Tlon lists and prepare a private comparison interface |
198−| 4e472b5 | 2026-10-31 | Pass known named unions through polymorphic gates |
199−| e3e184f | 2026-10-31 | Parse type holes, reject duplicate written record fields, and extend partial union inference and imports |
200−| 80e221a | 2026-10-31 | Infer supported annotation holes and prelude list aliases |
201−| ba1fec4 | 2026-10-31 | Add the curried `bond` prelude gate |
202−| 0ea700d | 2026-10-31 | Infer a source-defined recursive `qath` subset and record the explicit `proj` decision |
203−| 75f5952 | 2026-10-31 | Check a subset of explicit `proj` calls and retain their lowering evidence |
204−| cf17925 | 2026-10-31 | Infer supported single-field projections |
205−| 1a891e2 | 2026-10-31 | Infer source-backed addition and decrement without loobean operands; record the watchability decision |
206−| 81af5fd | 2026-10-31 | Preserve public names of identity-generic union aliases and record the `like` decision |
207−| 640a442 | 2026-10-31 | Add the source-backed `like` result mapper and infer supported positional calls |
208−| 445a0a1 | 2026-10-31 | Retain source-backed API path evidence and classify declarations |
209−| f69493d | 2026-10-31 | Derive supported request components from API declarations |
210−| f0f6954 | 2026-10-31 | Analyze supported API helper definitions and declared marks |
211−| 3f55af7 | 2026-10-31 | Define source-backed transparent ask and pure |
212−| ae1ec26 | 2026-10-31 | Prove selected default-wrapped Hoon unions from source |
213−| dde791c | 2026-10-31 | Infer a source-backed request-gate type through ordinary imports |
214−| a1c5f35 | 2026-10-31 | Infer supported multi-path requests and named closed folds |
215−| 911ca0c | 2026-10-31 | Propagate union context, define subscriptions and match literal nouns |
216−| 72acdb3 | 2026-10-31 | Infer selected nested union payloads from context |
217−| 706035c | 2026-10-31 | Analyze gate-free source molds with field witnesses |
218−| 651b8ec | 2026-10-31 | Match source-proven gate samples in direct calls |
219−| cc8e389 | 2026-10-31 | Add source-backed list length and real todo regression |
220−| 4da6891 | 2026-10-31 | Add source-backed comparisons and nested Hoon union controls |
221−| 09db390 | 2026-10-31 | Skip unnecessary inference environment scans |
222−| 179d717 | 2026-10-31 | Diagnose source-proven Hoon union overlaps |
223−| 142f2e2 | 2026-10-31 | Prove structural overlaps across Hoon union cases |
224−| c96597d | 2026-10-31 | Track source-proven generic recursive identities |
225−| 190a9d5 | 2026-10-31 | Add source-backed list flattening |
226−| d9d51e6 | 2026-10-31 | Check source-proven recursive tree construction |
227−| 30b0a9e | 2026-10-31 | Match source-proven recursive tree cases |
228−| 72d85ab | 2026-10-31 | Add bounded deferred inference and expand runtime equality coverage |
229−| 22f3788 | 2026-10-31 | Check empty molds and propagate closed cell context into branches |
230−| 341bcb4 | 2026-10-31 | Keep deferred fits stable under later substitutions |
231−| b93a94b | 2026-10-31 | Prove local generic-alias union tags and add successor |
232−| 2826c93 | 2026-10-31 | Report generic-alias overlaps and retain deferred branch contexts |
233−| b5cdc80 | 2026-10-31 | Preserve full-module overlap source evidence |
234−| ab6fdc1 | 2026-10-31 | Add source-backed text conversion wrappers |
235−| aa277c9 | 2026-10-31 | Recover prepared tuple initializers in partial reports |
236−| b4703e7 | 2026-11-01 | Check narrow closed subscription-free program mains |
237−| 26bf7a7 | 2026-11-01 | Recover narrow direct-program initializer contexts |
238−| 642d2c0 | 2026-11-01 | Prove direct request-value watchability for program subscriptions |
239−| 2e4d582 | 2026-11-01 | Add the source-backed UI, program and page prelude slice |
240−| a163965 | 2026-11-01 | Recover direct-program update result contexts |
241−| 46748b0 | 2026-11-01 | Check the unchanged todo island through component recovery |
242−| 1e17d5f | 2026-11-01 | Check static and direct data-page mains |
243−| 0517053 | 2026-11-01 | Add the theme mold and require explicit unit syntax |
244−| This change | 2026-11-01 | Check the unchanged cart store and basket |
245
288
246## Checking it
289## Checking it
247
290
248−On a machine set up as [development.md](development.md) says:
291+[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.
249−
250−```
251−tools/golden # 660 cases under urbit eval
252−tools/importer-test # the Hoon importer fixture projection
253−tools/type-import-default-test # default-wrapped source proof golden
254−tools/type-import-test # the importer/checker bridge fixture
255−tools/type-import-overlap-test # source-aware Hoon overlap and provenance fixture
256−tools/type-import-structural-test # structural overlap and multi-case source fixture
257−tools/type-union-source-test # local generic-alias union guards
258−tools/type-union-alias-overlap-test # local generic-alias overlap diagnostics
259−tools/type-full-overlap-test # full-module overlap evidence
260−tools/type-tlon-test # the real Tlon reader/checker fixture
261−tools/type-mark-test # the mark/checker bridge fixture
262−tools/type-poke-test # the source-backed poke/API fixture
263−tools/type-api-evidence-test # API declaration evidence guards
264−tools/type-api-paths-test # partial API path metadata fixture
265−tools/type-hole-guards-test # hole defaulting and API interface guards
266−tools/type-list-alias-test # prelude list-alias guards
267−tools/type-generic-alias-test # generic union alias guards
268−tools/type-generic-recursion-test # source-proven generic recursion guards
269−tools/type-generic-construction-test # source-proven recursive construction guards
270−tools/type-generic-pattern-test # source-proven recursive pattern guards
271−tools/type-deferred-test # source-owned deferred inference guards
272−tools/type-deferred-resolver-test # resolver consistency and failure guards
273−tools/type-deferred-context-test # deferred source-order and branch guards
274−tools/type-deferred-prepared-test # prepared initializer reports and failure guards
275−tools/type-empty-test # empty molds and coverage guards
276−tools/type-cell-branch-test # branch context and rollback guards
277−tools/type-positional-face-guards-test # positional sample face guards
278−tools/type-qath-guards-test # qath source and unfolding guards
279−tools/type-ask-guards-test # ask source and bootstrap guards
280−tools/type-proj-guards-test # projection evidence and scope guards
281−tools/type-buttons-test # documented buttons schemes and exact pending-tag error
282−tools/type-theme-test # byte-identical real theme, exact type and rejection guards
283−tools/type-module-scope-test # module and prelude scope fixture
284−tools/type-program-main-test # closed program-main interface and rejection guards
285−tools/type-program-init-test # transactional direct-program initializer context guards
286−tools/type-program-update-test # transactional direct-program update context guards
287−tools/type-program-watch-test # direct request-value watchability guards
288−tools/type-todo-full-test # byte-identical full todo and rejection guards
289−tools/hoon check-spans-test # prints <<>> when the span checker works
290−tools/testdata/selftest # the tools themselves
291−tools/doc-blocks docs/spec # the doc's examples are golden cases
292−tools/ship start
293−tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
294−tools/ship test # the same 660 cases as -test arms on the ship
295−tools/testdata/ship-selftest
296−tools/testdata/clay-fixtures-selftest # scratch fixture cleanup without a ship
297−tools/ship check-commit # |commit stores .jibb files
298−tools/clay-fixtures # example /sur files and marks build through Clay
299−```
300−
301−## What milestone 1 leaves to later milestones
302−
303−- 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).
304−- 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.
305−- Grammar questions the doc's author hasn't been asked follow the readings in [open-questions.md](open-questions.md).
flake.nix+3−2
@@ -90,7 +90,8 @@
90 '';
90 '';
91
91
92 # The desks, as tools/ship assembles them for the ship:
92 # The desks, as tools/ship assembles them for the ship:
93− # $out/my-app, $out/jibb and $out/jibb-dev, the test desk. The
93+ # $out/my-app, $out/jibb, $out/jibb-dev, the test desk, and
94+ # $out/jibb-fixtures, for the Clay fixtures. The
94 # check phase compiles the two libraries under urbit eval.
95 # check phase compiles the two libraries under urbit eval.
95 desks = pkgs.stdenvNoCC.mkDerivation {
96 desks = pkgs.stdenvNoCC.mkDerivation {
96 # No version in the name, so a commit that changes no desk
97 # No version in the name, so a commit that changes no desk
@@ -123,7 +124,7 @@
123 # The files are the desks' as they are: nothing to patch.
124 # The files are the desks' as they are: nothing to patch.
124 dontFixup = true;
125 dontFixup = true;
125 meta = {
126 meta = {
126− description = "The Jibb desks: my-app, jibb and jibb-dev";
127+ description = "The Jibb desks: my-app, jibb, jibb-dev and jibb-fixtures";
127 platforms = systems;
128 platforms = systems;
128 };
129 };
129 };
130 };
jibb-dev/lib/jibb-import.hoon−543
@@ -1717,127 +1717,6 @@
1717 ?~ first $(xs t.xs)
1717 ?~ first $(xs t.xs)
1718 first
1718 first
1719::
1719::
1720−:: +fixture-test: shared golden expectations for eval and the ship.
1721−:: A synthetic hold whose first $^ branch cannot be evaluated. It tests
1722−:: that a failed branch probe is reported rather than crashing the host.
1723−++ bad-branch-fixture
1724− ^- type
1725− [%hold -:!>(..zuse) [%tsls [%note [%made %bad ~] [%wtcl [%dtwt [%$ 12]] [%wing ~[%jibb-no-such-branch-name]] [%rock %n 0]]] [%$ 1]]]
1726−::
1727−++ fixture-test
1728− |= [small=@t epic=@t presence=@t docs=@t shadow=@t]
1729− ^- (list @t)
1730− =/ sc=type -:(ride -:!>(..zuse) small)
1731− =/ ec=type -:(ride -:!>(..zuse) epic)
1732− =/ pc=type -:(ride -:!>(..zuse) presence)
1733− =/ dc=type -:(ride -:!>(..zuse) docs)
1734− =/ hc=type -:(ride -:!>(..zuse) shadow)
1735− =/ sample
1736− |= name=term
1737− (read-mold-in %small name (~(play ut sc) (ream (cat 3 '*' name))) sc)
1738− =/ tlon
1739− |= name=term
1740− (read-mold-in %epic name (~(play ut ec) (ream (cat 3 '*' name))) ec)
1741− =/ present
1742− |= name=term
1743− (read-mold-in %presence name (~(play ut pc) (ream (cat 3 '*' name))) pc)
1744− =/ shad
1745− |= name=term
1746− (read-mold-in %shadow name (~(play ut hc) (ream (cat 3 '*' name))) hc)
1747− =/ docs-type
1748− |= name=term
1749− (read-mold-in %docs name (~(play ut dc) (ream (cat 3 '*' name))) dc)
1750− =/ errors=(list @t) ~
1751− =/ expect-action=imported
1752− [%fork ~[[%cell [%atom %tas [~ %add]] [%face %text [%atom %t ~]]] [%cell [%atom %tas [~ %remove]] [%face %id [%atom %ud ~]]]]]
1753− =/ errors ?: =((sample %action) [%& expect-action]) errors
1754− ['union cases and faces' errors]
1755− =/ expect-map=imported
1756− [%apply %map ~[[%atom %ud ~] [%cell [%face %id [%atom %ud ~]] [%face %text [%atom %t ~]]]]]
1757− =/ errors ?: =((sample %items) [%& expect-map]) errors
1758− ['map and its arguments' errors]
1759− =/ expect-optional=imported
1760− [%fork ~[[%cell [%face %name [%atom %t ~]] [%face %stamp [%atom %ud ~]]] [%atom %ud ~]]]
1761− =/ errors ?: =((sample %optional) [%& expect-optional]) errors
1762− ['atom-or-cell union' errors]
1763− =/ expect-containers=imported
1764− [%cell [%apply %set ~[[%atom %ud ~]]] [%cell [%apply %qeu ~[[%atom %ud ~]]] [%cell [%apply %list ~[[%atom %t ~]]] [%apply %unit ~[[%atom %ud ~]]]]]]
1765− =/ errors ?: =((sample %containers) [%& expect-containers]) errors
1766− ['set queue list and unit' errors]
1767− =/ expect-chain=imported
1768− [%fork ~[[%cell [%face %value [%atom %ud ~]] [%face %next [%ref %small %chain]]] [%atom %n [~ 0]]]]
1769− =/ errors ?: =((sample %chain) [%& expect-chain]) errors
1770− ['recursive reference' errors]
1771− =/ expect-jar=imported [%apply %jar ~[[%atom %ud ~] [%atom %t ~]]]
1772− =/ expect-jug=imported [%apply %jug ~[[%atom %ud ~] [%atom %t ~]]]
1773− =/ errors ?: =((sample %jar-test) [%& expect-jar]) errors
1774− ['jar name and arguments' errors]
1775− =/ errors ?: =((sample %jug-test) [%& expect-jug]) errors
1776− ['jug name and arguments' errors]
1777− =/ expect-nested-jar=imported [%face %field [%apply %jar ~[[%atom %ud ~] [%atom %t ~]]]]
1778− =/ errors ?: =((sample %nested-jar) [%& expect-nested-jar]) errors
1779− ['nested jar is preserved' errors]
1780− =/ expect-paired=imported
1781− [%cell [%face %values [%apply %jar ~[[%atom %ud ~] [%atom %t ~]]]] [%face %cache [%apply %jug ~[[%atom %ud ~] [%atom %t ~]]]]]
1782− =/ errors ?: =((sample %paired-aliases) [%& expect-paired]) errors
1783− ['multiple collection aliases are preserved' errors]
1784− =/ expect-nested-alias=imported
1785− [%apply %jar ~[[%atom %ud ~] [%apply %jug ~[[%atom %ud ~] [%atom %t ~]]]]]
1786− =/ errors ?: =((sample %nested-alias) [%& expect-nested-alias]) errors
1787− ['nested collection arguments preserve names' errors]
1788− =/ expect-mop=imported [%apply %mop ~[[%atom %ud ~] [%atom %t ~]]]
1789− =/ errors ?: =((sample %mop-test) [%& expect-mop]) errors
1790− ['ordered map name and arguments' errors]
1791− =/ expect-nested-mop=imported
1792− [%cell [%face %table expect-mop] [%face %other [%atom %ud ~]]]
1793− =/ errors ?: =((sample %nested-mop) [%& expect-nested-mop]) errors
1794− ['ordered map field is preserved' errors]
1795− =/ expect-mixed=imported
1796− [%cell [%face %a expect-mop] [%face %b [%apply %list ~[[%atom %ud ~]]]]]
1797− =/ errors ?: =((sample %mixed-mop) [%& expect-mixed]) errors
1798− ['static list sibling is preserved' errors]
1799− =/ errors ?: =((sample %named-mop) [%| 'a nested Hoon mop needs source-aware import']) errors
1800− ['non-atom argument remains unsupported' errors]
1801− =/ errors ?: =((sample %mop-list) [%| 'a nested Hoon mop needs source-aware import']) errors
1802− ['ordered map in a list remains unsupported' errors]
1803− =/ errors ?: =((sample %signed) [%| 'signed and float auras cannot be imported']) errors
1804− ['signed aura rejected' errors]
1805− =/ errors ?: =((sample %float) [%| 'signed and float auras cannot be imported']) errors
1806− ['float aura rejected' errors]
1807− =/ errors ?: =((sample %gate-test) [%| 'cores and gates cannot be imported']) errors
1808− ['gate rejected' errors]
1809− =/ errors ?: =((read-mold %std %vase (~(play ut -:!>(..zuse)) (ream '*vase'))) [%| 'vases cannot be imported']) errors
1810− ['vase rejected' errors]
1811− =/ expect-valid=imported
1812− [%fork ~[[%cell [%face %x [%atom %ud ~]] [%face %y [%atom %ud ~]]] [%atom %ud ~]]]
1813− =/ errors ?: =((sample %valid-cell) [%& expect-valid]) errors
1814− ['disjoint cell union' errors]
1815− =/ errors ?: =((sample %invalid-cell) [%| 'Hoon $^ union disjointness could not be verified']) errors
1816− ['overlapping cell union is rejected' errors]
1817− =/ errors ?: =((shad %mn) [%| 'Hoon collection provenance is unavailable or shadowed']) errors
1818− ['local mop shadow in a field is rejected' errors]
1819− =/ errors ?: =((shad %mm) [%| 'Hoon collection provenance is unavailable or shadowed']) errors
1820− ['local mop shadow is rejected' errors]
1821− =/ errors ?: =((shad %aa) [%| 'Hoon collection provenance is unavailable or shadowed']) errors
1822− ['local jar shadow is rejected' errors]
1823− =/ errors ?: =((shad %bb) [%| 'Hoon collection provenance is unavailable or shadowed']) errors
1824− ['local jug shadow in a field is rejected' errors]
1825− =/ errors ?: =((read-mold %small %jar-test (~(play ut sc) (ream '*jar-test'))) [%| 'Hoon collection provenance is unavailable or shadowed']) errors
1826− ['missing provenance is rejected' errors]
1827− =/ expect-timing=imported
1828− [%cell [%face %since [%atom %da ~]] [%face %timeout [%apply %unit ~[[%atom %dr ~]]]]]
1829− =/ errors ?: =((present %timing) [%& expect-timing]) errors
1830− ['Tlon presence timing' errors]
1831− =/ errors ?: =((read-mold %external %bad bad-branch-fixture) [%| 'a Hoon $^ union needs a source-level disjointness check']) errors
1832− ['failed branch expansion is reported' errors]
1833− =/ expect-saga=imported
1834− [%fork ~[[%cell [%atom %tas [~ %chi]] [%atom %n [~ 0]]] [%cell [%atom %tas [~ %lev]] [%atom %n [~ 0]]] [%cell [%atom %tas [~ %dex]] [%face %ver [%atom %ud ~]]]]]
1835− =/ errors ?: =((tlon %saga) [%& expect-saga]) errors
1836− ['Tlon saga union' errors]
1837− =/ errors ?: =((tlon %epic) [%& [%atom %ud ~]]) errors
1838− ['Tlon epic atom' errors]
1839− errors
1840−
1841:: A compact diagnostic projection for importer golden files. This is
1720:: A compact diagnostic projection for importer golden files. This is
1842:: not the Jibb type printer: it exposes constants and recursive refs.
1721:: not the Jibb type printer: it exposes constants and recursive refs.
1843++ show-import
1722++ show-import
@@ -1883,426 +1762,4 @@
1883 [%invalid *] "invalid/{(trip code.result)}: {(trip message.result)}"
1762 [%invalid *] "invalid/{(trip code.result)}: {(trip message.result)}"
1884 [%unsupported *] "unsupported: {(trip message.result)}"
1763 [%unsupported *] "unsupported: {(trip message.result)}"
1885 ==
1764 ==
1886−::
1887−:: Clay includes debug spans around source nodes. Reproduce that
1888−:: shape without Clay so the same regression runs under eval and -test.
1889−++ decorate-union-source
1890− |= h=hoon
1891− ^- hoon
1892− =/ at=spot [/tests/importer/synthetic/hoon [[1 1] [1 2]]]
1893− ?^ -.h [%dbug at [$(h -.h) $(h +.h)]]
1894− ?+ h [%dbug at h]
1895− [%note *] [%dbug at h(q $(h q.h))]
1896− [%ktts *] [%dbug at h(q $(h q.h))]
1897− [%wtcl *] [%dbug at h(q $(h q.h), r $(h r.h))]
1898− ==
1899−::
1900−++ debug-union-fixture
1901− |= [cor=type name=term]
1902− ^- (each imported @t)
1903− =/ typ=type (~(play ut cor) (ream (cat 3 '*' name)))
1904− ?. ?=([%hold *] typ) [%| 'synthetic union is not a hold']
1905− =/ original=hoon q.typ
1906− ?. ?=([%tsls [%note * *] *] original) [%| 'synthetic union source is unavailable']
1907− =/ source=hoon original(q.p (decorate-union-source q.p.original))
1908− (read-mold %small name typ(q source))
1909−::
1910−:: Test debug metadata at the spec boundary without assuming that the
1911−:: eval version of Hoon's spec mold itself includes Clay's %dbug tag.
1912−++ debug-spec-fixture
1913− ^- tape
1914− =/ location=* [/tests/importer/synthetic/hoon [[1 1] [1 2]]]
1915− =/ wrapped=* [%dbug location [%leaf %tas %x]]
1916− =/ got=(unit *) (source-gist-tail wrapped)
1917− ?~ got "debug wrapper missing"
1918− =/ leaf=(each spec tang) (mule |.(;;(spec u.got)))
1919− ?. ?=([%& [%leaf %tas %x]] leaf) "debug leaf not recovered"
1920− =/ branch=spec [%bccl ~[p.leaf [%base [%atom %t]]]]
1921− ?^ (tagged-cases ~[branch branch] ~) "duplicate tags accepted"
1922− =/ broken=(unit *) (source-gist-tail [%dbug location 42])
1923− ?~ broken "debug wrapper missing"
1924− =/ invalid=(each spec tang) (mule |.(;;(spec u.broken)))
1925− ?: ?=(%& -.invalid) "malformed spec accepted"
1926− "valid wrapper; duplicate and malformed rejected"
1927−::
1928−:: The same named-operand call with Clay-style source-location wrappers.
1929−++ debug-mop-fixture
1930− |= cor=type
1931− ^- tape
1932− =/ typ=type (~(play ut cor) (ream '*mop-wing-valid'))
1933− ?> ?=([%hold *] typ)
1934− =/ original=hoon q.typ
1935− ?> ?=([%tsls [%note * *] *] original)
1936− =/ body=hoon q.p.original
1937− ?> ?=([%cncl *] body)
1938− ?> ?=([%tsgr *] p.body)
1939− =/ b=hoon q.p.body
1940− ?> ?=([%cncl *] b)
1941− =/ call=hoon p.b
1942− ?> ?=([%cncl *] call)
1943− ?> ?=([* [* ~]] q.call)
1944− =/ at=spot [/tests/importer/synthetic/hoon [[1 1] [1 2]]]
1945− =/ inner=hoon call(p [%dbug at p.call], q ~[[%dbug at i.q.call] [%dbug at i.t.q.call]])
1946− =/ outer=hoon body(p p.body(q b(p [%dbug at inner])))
1947− =/ mixed=hoon body(p p.body(q b(p inner)))
1948− =/ multi=hoon body(p p.body(q b(p call(p [%dbug at [%wing ~[%one %two]]]))))
1949− =/ plain=(unit [key=spec value=spec]) (mop-specs body)
1950− ?~ plain "unwrapped mop not recognized"
1951− ?. =((mop-specs [%dbug at outer]) plain) "wrapped mop not recognized"
1952− ?. =((mop-specs mixed) plain) "mixed mop not recognized"
1953− ?^ (mop-specs multi) "multi-segment callee accepted"
1954− ?^ (mop-specs [%dbug at [%sand %ud 42]]) "malformed call accepted"
1955− ?^ (source-single-wing [%dbug at 42]) "malformed wing accepted"
1956− ?^ (source-single-wing [%dbug at [%wing ~[%one %two]]]) "multi-segment operand accepted"
1957− =/ four=* [%dbug at [%dbug at [%dbug at [%dbug at [%wing ~[%mop]]]]]]
1958− =/ five=* [%dbug at four]
1959− ?~ (source-single-wing four) "four wrappers rejected"
1960− ?^ (source-single-wing five) "wrapper limit exceeded"
1961− ?~ (source-note-unwrap four 4) "four note wrappers rejected"
1962− ?^ (source-note-unwrap five 4) "note wrapper limit exceeded"
1963− =/ selected=(unit hoon) (local-arm-source cor %tag-valid)
1964− ?~ selected "selected union not found"
1965− =/ arm-four=hoon [%dbug at [%dbug at [%dbug at [%dbug at u.selected]]]]
1966− =/ arm-five=hoon [%dbug at arm-four]
1967− ?~ (tagged-source-code arm-four %tag-valid) "four wrapped selected arms rejected"
1968− ?^ (tagged-source-code arm-five %tag-valid) "selected arm wrapper limit exceeded"
1969− "wrapped and mixed calls accepted; malformed, multi-segment and excessive wrappers rejected"
1970−::
1971−:: Synthetic nodes test each part of the direct collection-call proof.
1972−++ collection-wrapper-fixture
1973− ^- tape
1974− =/ call=hoon [%cncl [%tsgr [%wing ~[[%.y 7]]] [%cncl [%wing ~[%list]] ~]] ~[[%$ 6]]]
1975− =/ subject=hoon [%cncl [%tsgr [%wing ~[[%.y 8]]] [%cncl [%wing ~[%list]] ~]] ~[[%$ 6]]]
1976− =/ sample=hoon [%cncl [%tsgr [%wing ~[[%.y 7]]] [%cncl [%wing ~[%list]] ~]] ~[[%$ 2]]]
1977− =/ good=hoon [%tsls [%note [%made %x ~] call] [%tsls [%dtts [%$ 14] [%$ 2]] [%$ 6]]]
1978− =/ tail=hoon [%tsls [%note [%made %x ~] call] [%$ 6]]
1979− =/ args=(list [hoon hoon]) ~[[call good] [subject good] [sample good] [call tail]]
1980− =/ flags=(list ?) (turn args |=(pair=[hoon hoon] (direct-collection-source -.pair +.pair)))
1981− ?: =(flags ~[& | | |]) "valid; forged subject, sample and tail rejected"
1982− "wrapper guard failed"
1983−::
1984−++ overlap-fork-fixture
1985− ^- type
1986− =/ nodes=(list type) ~[[%atom %ud ~] [%atom %t ~]]
1987− [%fork (silt nodes)]
1988−::
1989−++ invalid-fork-fixture
1990− ^- type
1991− =/ nodes=(list type) ~[[%atom %ud ~] [%atom %sd ~]]
1992− [%fork (silt nodes)]
1993−::
1994−++ fixture-output
1995− |= [small=@t epic=@t presence=@t docs=@t shadow=@t shadow-static=@t ford=@t mark=@t mark-rec=@t mark-gate=@t mark-basic=@t origin-trans=@t origin-first=@t origin-other=@t]
1996− ^- wain
1997− =/ sc=type -:(ride -:!>(..zuse) small)
1998− =/ ec=type -:(ride -:!>(..zuse) epic)
1999− =/ pc=type -:(ride -:!>(..zuse) presence)
2000− =/ dc=type -:(ride -:!>(..zuse) docs)
2001− =/ hc=type -:(ride -:!>(..zuse) shadow)
2002− =/ xc=type -:(ride -:!>(..zuse) shadow-static)
2003− =/ fp=type [%cell [%face %small sc] -:!>(..zuse)]
2004− =/ other=type -:(ride -:!>(..zuse) origin-other)
2005− =/ fc=type -:(ride fp ford)
2006− ?> ?=([%core *] fc)
2007− =/ only-list=@t '|%\0a+$ lists (list @ud)\0a--\0a'
2008− =/ tp=type [%cell [%face %intermediate fc] -:!>(..zuse)]
2009− =/ tc=type -:(ride tp only-list)
2010− =/ sp=type [%cell [%face %small xc] -:!>(..zuse)]
2011− =/ shc=type -:(ride sp only-list)
2012− =/ mark-core=type -:(ride fp mark)
2013− =/ mark-rec-core=type -:(ride fp mark-rec)
2014− =/ mark-gate-core=type -:(ride -:!>(..zuse) mark-gate)
2015− =/ mark-basic-core=type -:(ride -:!>(..zuse) mark-basic)
2016− =/ make-mark
2017− |= [field=@t scope=type]
2018− ^- type
2019− -:(ride scope (crip "|_ a={(trip field)}\0a++ grab |% ++ noun a --\0a++ grow |% ++ noun a --\0a++ grad %noun\0a--\0a"))
2020− =/ mark-union-core=type (make-mark 'mark-flag-valid:small' fp)
2021− =/ mark-overlap-core=type (make-mark 'mark-flag-overlap:small' fp)
2022− =/ mark-hidden-core=type (make-mark 'mark-flag-hidden:small' fp)
2023− =/ mark-signed-core=type (make-mark 'signed:small' fp)
2024− =/ mark-callable-core=type (make-mark 'gate-test:small' fp)
2025− =/ extra-subject=type [%cell [%face %other other] fp]
2026− =/ mark-extra-core=type (make-mark 'mark-flag-valid:small' extra-subject)
2027− =/ other-hold=type (~(play ut other) (ream '*chain'))
2028− =/ recursive-hold=type (~(play ut sc) (ream '*chain'))
2029− =/ fake-vase=type -:(ride -:!>(..zuse) '|%\0a+$ vase @ud\0a--\0a')
2030− =/ spoof=(unit import-diagnostic)
2031− (first-invalid [%bad 'signed and float auras cannot be imported'])
2032− ?> ?=(^ spoof)
2033− =/ mark-shadow-core=type -:(ride sp mark-basic)
2034− =/ tshp=type [%cell [%face %intermediate shc] -:!>(..zuse)]
2035− =/ tshc=type -:(ride tshp only-list)
2036− =/ trans=type -:(ride tp origin-trans)
2037− =/ ambiguous-parent=type [%cell [%face %first sc] [%cell [%face %second sc] -:!>(..zuse)]]
2038− =/ ambiguous=type -:(ride ambiguous-parent origin-first)
2039− =/ distinct-parent=type [%cell [%face %first sc] [%cell [%face %second other] -:!>(..zuse)]]
2040− =/ distinct=type -:(ride distinct-parent origin-first)
2041− =/ trans-amb-parent=type [%cell [%face %intermediate fc] [%cell [%face %second sc] -:!>(..zuse)]]
2042− =/ trans-amb=type -:(ride trans-amb-parent origin-trans)
2043− =/ tag-child=@t
2044− '|%\0a+$ tag-invalid-cell @t\0a+$ choice $%([%ok a=tag-invalid-cell] [%err a=@ud])\0a--\0a'
2045− =/ tag-collision=type -:(ride [%cell [%face %base sc] -:!>(..zuse)] tag-child)
2046− =/ tag-clean=type -:(ride [%cell [%face %base other] -:!>(..zuse)] tag-child)
2047− =/ tag-zuse=@t
2048− '|%\0a+$ ship @t\0a+$ path @ud\0a+$ choice $%([%ok who=ship] [%err where=path])\0a--\0a'
2049− =/ tag-zuse-core=type -:(ride -:!>(..zuse) tag-zuse)
2050− =/ nest-parent-src=@t
2051− '|%\0a+$ tag-nest-inner $%([%foreign @t] [%foreign @t])\0a--\0a'
2052− =/ nest-parent=type -:(ride -:!>(..zuse) nest-parent-src)
2053− =/ nest-child-src=@t
2054− '|%\0a+$ tag-nest-inner $%([%left @t] [%right @ud])\0a+$ tag-nest-middle $%([%one x=tag-nest-inner] [%two ~])\0a--\0a'
2055− =/ nest-collision=type -:(ride [%cell [%face %base nest-parent] -:!>(..zuse)] nest-child-src)
2056− =/ self-parent=type
2057− -:(ride -:!>(..zuse) '|%\0a+$ tag-self ?(%same %same)\0a--\0a')
2058− =/ self-child=@t
2059− '|%\0a+$ tag-self $%([%branch children=(list tag-self)] [%leaf value=@t])\0a--\0a'
2060− =/ self-collision=type -:(ride [%cell [%face %tag-self self-parent] -:!>(..zuse)] self-child)
2061− =/ self-other=type
2062− -:(ride -:!>(..zuse) '|%\0a+$ tag-self $%([%branch children=(list tag-self)] [%leaf value=@ud])\0a--\0a')
2063− =/ mop-ford-parent=type
2064− -:(ride -:!>(..zuse) '|%\0a+$ value ?(%same %same)\0a--\0a')
2065− =/ mop-ford-child=type
2066− -:(ride [%cell [%face %value mop-ford-parent] -:!>(..zuse)] '|%\0a+$ key @ud\0a+$ value @t\0a+$ mm ((mop key value) lte)\0a--\0a')
2067− =/ sample
2068− |= name=term
2069− (read-mold-in %small name (~(play ut sc) (ream (cat 3 '*' name))) sc)
2070− =/ tlon
2071− |= name=term
2072− (read-mold-in %epic name (~(play ut ec) (ream (cat 3 '*' name))) ec)
2073− =/ present
2074− |= name=term
2075− (read-mold-in %presence name (~(play ut pc) (ream (cat 3 '*' name))) pc)
2076− =/ shad
2077− |= name=term
2078− (read-mold-in %shadow name (~(play ut hc) (ream (cat 3 '*' name))) hc)
2079− =/ docs-type
2080− |= name=term
2081− (read-mold-in %docs name (~(play ut dc) (ream (cat 3 '*' name))) dc)
2082− =/ chapter-tree=(map term hoon)
2083− (~(put by *(map term hoon)) %jar [%zpzp ~])
2084− =/ vase (read-mold %std %vase (~(play ut -:!>(..zuse)) (ream '*vase')))
2085− :~ (crip "action: {(show-result (sample %action))}")
2086− (crip "optional: {(show-result (sample %optional))}")
2087− (crip "items: {(show-result (sample %items))}")
2088− (crip "containers: {(show-result (sample %containers))}")
2089− (crip "chain: {(show-result (sample %chain))}")
2090− (crip "jar: {(show-result (sample %jar-test))}")
2091− (crip "jug: {(show-result (sample %jug-test))}")
2092− (crip "nested-jar: {(show-result (sample %nested-jar))}")
2093− (crip "paired-aliases: {(show-result (sample %paired-aliases))}")
2094− (crip "nested-alias: {(show-result (sample %nested-alias))}")
2095− (crip "compound: {(show-result (sample %compound))}")
2096− (crip "compound-fields: {(show-result (sample %compound-fields))}")
2097− (crip "mop: {(show-result (sample %mop-test))}")
2098− (crip "nested-mop: {(show-result (sample %nested-mop))}")
2099− (crip "two-mops: {(show-result (sample %two-mops))}")
2100− (crip "mixed-mop: {(show-result (sample %mixed-mop))}")
2101− (crip "nested-static-mop: {(show-result (sample %nested-static-mop))}")
2102− (crip "collection-siblings: {(show-result (sample %collection-siblings))}")
2103− (crip "dynamic-sibling-mop: {(show-result (sample %dynamic-sibling-mop))}")
2104− (crip "mark-flag-source: {(show-result (read-named %small %mark-flag-valid sc))}")
2105− (crip "mark-flag-union: {(show-result (read-mark %flag-union mark-union-core))}")
2106− (crip "mark-flag-overlap: {(show-result (read-mark %flag-overlap mark-overlap-core))}")
2107− (crip "mark-flag-hidden: {(show-result (read-mark %flag-hidden mark-hidden-core))}")
2108− (crip "mark-flag-signed: {(show-result (read-mark %flag-signed mark-signed-core))}")
2109− (crip "mark-flag-callable: {(show-result (read-mark %flag-callable mark-callable-core))}")
2110− (crip "mark-flag-extra: {(show-result (read-mark %flag-extra mark-extra-core))}")
2111− (crip "mark-flag-other-hold: {?~((mark-union-fallback other-hold fp) "unsupported" "BAD")}")
2112− (crip "mark-flag-recursive-fallback: {?~((mark-union-fallback recursive-hold fp) "unsupported" "BAD")}")
2113− (crip "mark-record: {(show-result (read-mark %todo-item mark-core))}")
2114− (crip "mark-recursive: {(show-result (read-mark %recursive mark-rec-core))}")
2115− (crip "mark-gate: {(show-result (read-mark %bad mark-gate-core))}")
2116− (crip "mark-list: {(show-result (read-mark %list-mark mark-basic-core))}")
2117− (crip "mark-shadow: {(show-result (read-mark %list-mark mark-shadow-core))}")
2118− (crip "mark-not-core: {(show-result (read-mark %bad [%atom %ud ~]))}")
2119− (crip "ford-list: {(show-result (read-mold-in %ford %lists (~(play ut fc) (ream '*lists')) fc))}")
2120− (crip "ford-imported: {(show-result (read-mold-in %ford %wrapped (~(play ut fc) (ream '*wrapped')) fc))}")
2121− (crip "ford-recursive: {(show-result (read-mold-in %ford %recursive (~(play ut fc) (ream '*recursive')) fc))}")
2122− (crip "ford-local-recursive: {(show-result (read-mold-in %ford %local (~(play ut fc) (ream '*local')) fc))}")
2123− (crip "ford-recursive-transitive: {(show-result (read-named %outer %wrapped trans))}")
2124− (crip "ford-recursive-ambiguous: {(show-result (read-named %outer %pick-one ambiguous))}")
2125− (crip "ford-recursive-transitive-ambiguous: {(show-result (read-named %outer %wrapped trans-amb))}")
2126− (crip "ford-recursive-distinct-first: {(show-result (read-named %outer %pick-one distinct))}")
2127− (crip "ford-recursive-distinct-second: {(show-result (read-named %outer %pick-two distinct))}")
2128− (crip "ford-transitive: {(show-result (read-mold-in %ford %lists (~(play ut tc) (ream '*lists')) tc))}")
2129− (crip "ford-shadow: {(show-result (read-mold-in %ford %lists (~(play ut shc) (ream '*lists')) shc))}")
2130− (crip "ford-transitive-shadow: {(show-result (read-mold-in %ford %lists (~(play ut tshc) (ream '*lists')) tshc))}")
2131− (crip "ford-shadow-face: {?:((scope-safe [%cell [%face %list sc] -:!>(..zuse)] %list) "wrong" "unsafe")}")
2132− (crip "ford-unknown: {?:((scope-safe [%cell [%atom %ud ~] -:!>(..zuse)] %list) "wrong" "unsafe")}")
2133− (crip "ford-mismatched-core: {?:((scope-safe fc(p -:!>(..zuse)) %list) "wrong" "unsafe")}")
2134− (crip "shadow-list-mop: {(show-result (read-mold-in %shadow-static %bad (~(play ut xc) (ream '*bad')) xc))}")
2135− (crip "named-mop: {(show-result (sample %named-mop))}")
2136− (crip "mop-list: {(show-result (sample %mop-list))}")
2137− (crip "mop-wing-valid: {(show-result (sample %mop-wing-valid))}")
2138− (crip "mop-wing-invalid-key: {(show-result (sample %mop-wing-invalid-key))}")
2139− (crip "mop-wing-invalid-key-alias: {(show-result (sample %mop-wing-invalid-key-alias))}")
2140− (crip "mop-wing-invalid-value: {(show-result (sample %mop-wing-invalid-value))}")
2141− (crip "mop-wing-invalid-value-alias: {(show-result (sample %mop-wing-invalid-value-alias))}")
2142− (crip "mop-wing-rec-key: {(show-result (sample %mop-wing-rec-key))}")
2143− (crip "mop-wing-rec-value: {(show-result (sample %mop-wing-rec-value))}")
2144− (crip "mop-wing-shadow: {(show-result (read-named %shadow %mmw hc))}")
2145− (crip "mop-wing-ford-collision: {(show-result (read-named %child %mm mop-ford-child))}")
2146− (crip "mop-wing-debug: {(debug-mop-fixture sc)}")
2147− (crip "signed: {(show-result (sample %signed))}")
2148− (crip "float: {(show-result (sample %float))}")
2149− (crip "gate: {(show-result (sample %gate-test))}")
2150− (crip "vase: {(show-result vase)}")
2151− (crip "failed-branch: {(show-result (read-mold %external %bad bad-branch-fixture))}")
2152− (crip "debug-spec: {debug-spec-fixture}")
2153− (crip "debug-union: {(show-result (debug-union-fixture sc %action))}")
2154− (crip "debug-union-overlap: {(show-result (debug-union-fixture sc %explicit-wut-overlap))}")
2155− (crip "debug-nested-cell: {(show-result (debug-union-fixture sc %nested-valid-cell))}")
2156− (crip "debug-nested-cell-overlap: {(show-result (debug-union-fixture sc %nested-invalid-cell))}")
2157− (crip "explicit-graph: {(show-result (read-mold %raw %raw overlap-fork-fixture))}")
2158− (crip "explicit-graph-unsupported: {(show-result (read-mold %raw %raw invalid-fork-fixture))}")
2159− (crip "explicit-wut-safe: {(show-result (sample %explicit-wut-safe))}")
2160− (crip "explicit-percent-overlap: {(show-result (sample %explicit-percent-overlap))}")
2161− (crip "explicit-wut-overlap: {(show-result (sample %explicit-wut-overlap))}")
2162− (crip "explicit-collapsed: {(show-result (sample %explicit-collapsed))}")
2163− (crip "explicit-subsumed: {(show-result (sample %explicit-subsumed))}")
2164− (crip "explicit-three: {(show-result (sample %explicit-three))}")
2165− (crip "explicit-unknown: {(show-result (sample %explicit-unknown))}")
2166− (crip "explicit-nested: {(show-result (sample %explicit-nested))}")
2167− (crip "collection-union-wrapper: {collection-wrapper-fixture}")
2168− (crip "collection-union-list: {(show-result (sample %collection-union-list))}")
2169− (crip "collection-union-set: {(show-result (sample %collection-union-set))}")
2170− (crip "collection-union-map-key: {(show-result (sample %collection-union-map-key))}")
2171− (crip "collection-union-map-value: {(show-result (sample %collection-union-map-value))}")
2172− (crip "collection-union-unit: {(show-result (sample %collection-union-unit))}")
2173− (crip "collection-union-collapsed: {(show-result (sample %collection-union-collapsed))}")
2174− (crip "collection-union-multiple: {(show-result (sample %collection-union-multiple))}")
2175− (crip "collection-union-nested: {(show-result (sample %collection-union-nested))}")
2176− (crip "collection-union-dependent: {(show-result (sample %collection-union-dependent))}")
2177− (crip "collection-union-shadow: {(show-result (read-named %shadow %collection-union-shadow xc))}")
2178− (crip "explicit-list: {(show-result (sample %explicit-list))}")
2179− (crip "explicit-set: {(show-result (sample %explicit-set))}")
2180− (crip "explicit-faces: {(show-result (sample %explicit-faces))}")
2181− (crip "explicit-alias: {(show-result (sample %explicit-alias))}")
2182− (crip "explicit-ford: {(show-result (read-named %outer %bad-union trans))}")
2183− (crip "explicit-shadow-path: {(show-result (read-named %shadow %path-shadow xc))}")
2184− (crip "list-bckt-field: {(show-result (sample %list-bckt-field))}")
2185− (crip "list-noun-overlap: {(show-result (sample %list-noun-overlap))}")
2186− (crip "list-null-overlap: {(show-result (sample %list-null-overlap))}")
2187− (crip "list-nested-atom-cell: {(show-result (sample %list-nested-atom-cell))}")
2188− (crip "list-nested-valid-cell: {(show-result (sample %list-nested-valid-cell))}")
2189− (crip "list-nested-invalid-cell: {(show-result (sample %list-nested-invalid-cell))}")
2190− (crip "map-nested-invalid-cell: {(show-result (sample %map-nested-invalid-cell))}")
2191− (crip "set-direct-invalid-cell: {(show-result (sample %set-direct-invalid-cell))}")
2192− (crip "map-key-invalid-cell: {(show-result (sample %map-key-invalid-cell))}")
2193− (crip "nested-atom-cell: {(show-result (sample %nested-atom-cell))}")
2194− (crip "nested-tags: {(show-result (sample %nested-tags))}")
2195− (crip "nested-tags-overlap: {(show-result (sample %nested-tags-overlap))}")
2196− (crip "nested-tagged: {(show-result (sample %nested-tagged))}")
2197− (crip "nested-tagged-bckt: {(show-result (sample %nested-tagged-bckt))}")
2198− (crip "nested-tagged-overlap: {(show-result (sample %nested-tagged-overlap))}")
2199− (crip "nested-tagged-alias: {(show-result (sample %nested-tagged-alias))}")
2200− (crip "nested-tagged-ford: {(show-result (read-named %outer %tagged trans))}")
2201− (crip "tag-static-valid: {?:((fixed-cell-mold [%wtgr [%dtts [%$ 13] [%rock %$ %foo]] [%rock %tas %foo]] 13) "yes" "no")}")
2202− (crip "tag-static-wrong-axis: {?:((fixed-cell-mold [%wtgr [%dtts [%$ 12] [%rock %$ %foo]] [%rock %tas %foo]] 13) "wrong" "no")}")
2203− (crip "tag-static-nonconstant: {?:((fixed-cell-mold [%wtgr [%dtts [%$ 13] [%rock %$ %foo]] [%$ 13]] 13) "wrong" "no")}")
2204− (crip "tag-static-wrong-value: {?:((fixed-cell-mold [%wtgr [%dtts [%$ 13] [%rock %$ %foo]] [%rock %tas %bar]] 13) "wrong" "no")}")
2205− (crip "nested-first-cell: {(show-result (sample %nested-first-cell))}")
2206− (crip "nested-alias-cell: {(show-result (sample %nested-alias-cell))}")
2207− (crip "nested-multiple-cell: {(show-result (sample %nested-multiple-cell))}")
2208− (crip "nested-named-sibling: {(show-result (sample %nested-named-sibling))}")
2209− (crip "nested-list-sibling: {(show-result (sample %nested-list-sibling))}")
2210− (crip "nested-validated-sibling: {(show-result (sample %nested-validated-sibling))}")
2211− (crip "nested-validated-branch: {(show-result (sample %nested-validated-branch))}")
2212− (crip "nested-named-branch: {(show-result (sample %nested-named-branch))}")
2213− (crip "nested-ford-cell: {(show-result (read-named %outer %nested trans))}")
2214− (crip "nested-valid-cell: {(show-result (sample %nested-valid-cell))}")
2215− (crip "nested-invalid-cell: {(show-result (sample %nested-invalid-cell))}")
2216− (crip "valid-cell: {(show-result (sample %valid-cell))}")
2217− (crip "invalid-cell: {(show-result (sample %invalid-cell))}")
2218− (crip "chapter-malformed: {?:((chapter-unsafe [%x %y %z] %jar) "unsafe" "wrong")}")
2219− (crip "chapter-wrapped-malformed: {?:((chapter-unsafe [~ [%x %y %z]] %jar) "unsafe" "wrong")}")
2220− (crip "chapter-direct-hit: {?:(=((chapter-has chapter-tree %jar) [~ &]) "yes" "no")}")
2221− (crip "chapter-wrapped-hit: {?:(=((chapter-has [~ chapter-tree] %jar) [~ &]) "yes" "no")}")
2222− (crip "chapter-direct-miss: {?:(=((chapter-has chapter-tree %jug) [~ &]) "yes" "no")}")
2223− (crip "chapter-wrapped-miss: {?:(=((chapter-has [~ chapter-tree] %jug) [~ &]) "yes" "no")}")
2224− (crip "shadow-nested-mop: {(show-result (shad %mn))}")
2225− (crip "shadow-mop: {(show-result (shad %mm))}")
2226− (crip "shadow-jar: {(show-result (shad %aa))}")
2227− (crip "shadow-jug: {(show-result (shad %bb))}")
2228− (crip "no-provenance-atom: {(show-result (read-mold %small %word (~(play ut sc) (ream '*word'))))}")
2229− (crip "no-provenance-recursive: {(show-result (read-mold %wrong %alias (~(play ut sc) (ream '*chain'))))}")
2230− (crip "no-provenance: {(show-result (read-mold %small %jar-test (~(play ut sc) (ream '*jar-test'))))}")
2231− (crip "named-not-mold: {(show-result (read-named %small %not-mold sc))}")
2232− (crip "named-present: {(show-result (read-named %small %items sc))}")
2233− (crip "named-missing: {(show-result (read-named %small %missing sc))}")
2234− (crip "named-invalid-core: {(show-result (read-named %small %items [%atom %ud ~]))}")
2235− (crip "named-ford-recursive: {(show-result (read-named %ford %recursive fc))}")
2236− (crip "diagnostic-items: {(show-import-diagnostic (read-named-diagnostic %small %items sc))}")
2237− (crip "diagnostic-signed: {(show-import-diagnostic (read-named-diagnostic %small %signed sc))}")
2238− (crip "diagnostic-float: {(show-import-diagnostic (read-named-diagnostic %small %float sc))}")
2239− (crip "diagnostic-overlap: {(show-import-diagnostic (read-named-diagnostic %small %explicit-percent-overlap sc))}")
2240− (crip "diagnostic-unproved: {(show-import-diagnostic (read-named-diagnostic %small %list-nested-invalid-cell sc))}")
2241− (crip "diagnostic-mark-gate: {(show-import-diagnostic (read-mark-diagnostic %bad mark-gate-core))}")
2242− (crip "diagnostic-shadow-vase: {(show-import-diagnostic (read-named-diagnostic %fake %vase fake-vase))}")
2243− (crip "diagnostic-spoof: {(show-import-diagnostic u.spoof)}")
2244− (crip "missing-arm: {(show-result (read-mold-in %small %missing [%atom %ud ~] sc))}")
2245− (crip "wrong-provenance: {(show-result (read-mold-in %small %action (~(play ut sc) (ream '*items')) sc))}")
2246− (crip "unverified-subject: {(show-result (read-mold-in %std %jar (~(play ut -:!>(..zuse)) (ream '*(jar @ud @t)')) -:!>(..zuse)))}")
2247− (crip "tag-ford-collision: {(show-result (read-named %child %choice tag-collision))}")
2248− (crip "tag-ford-clean: {(show-result (read-named %child %choice tag-clean))}")
2249− (crip "tag-zuse-local: {(show-result (read-named %child %choice tag-zuse-core))}")
2250− (crip "tag-nest-inner: {(show-result (sample %tag-nest-inner))}")
2251− (crip "tag-nest-middle: {(show-result (sample %tag-nest-middle))}")
2252− (crip "tag-nest-diamond: {(show-result (sample %tag-nest-diamond))}")
2253− (crip "tag-nest-deep: {(show-result (sample %tag-nest-deep))}")
2254− (crip "tag-nest-hidden: {(show-result (sample %tag-nest-hidden))}")
2255− (crip "tag-nest-overlap: {(show-result (sample %tag-nest-overlap))}")
2256− (crip "tag-nest-recursive: {(show-result (sample %tag-nest-recursive-outer))}")
2257− (crip "tag-nest-rec-list: {(show-result (sample %tag-nest-rec-list-outer))}")
2258− (crip "tag-nest-rec-repeat: {(show-result (sample %tag-nest-rec-repeat))}")
2259− (crip "tag-nest-rec-duplicate: {(show-result (sample %tag-nest-rec-bad-outer))}")
2260− (crip "tag-nest-rec-hidden: {(show-result (sample %tag-nest-rec-hidden-outer))}")
2261− (crip "tag-nest-rec-mutual: {(show-result (sample %tag-nest-rec-mutual-outer))}")
2262− (crip "tag-nest-rec-outer-overlap: {(show-result (sample %tag-nest-rec-outer-overlap))}")
2263− (crip "tag-nest-rec-owner: {?:(&((contains-named-ref [%ref %small %tag-self] %small %tag-self) !(contains-named-ref [%named %small %other [%ref %small %tag-self]] %small %tag-self)) "yes" "wrong")}")
2264− (crip "tag-nest-many: {(show-result (sample %tag-nest-many))}")
2265− (crip "tag-nest-shadow: {(show-result (read-named %shadow-static %tag-nest-shadow xc))}")
2266− (crip "tag-nest-wrong-hold: {?~((nested-tagged-union %small (~(play ut other) (ream '*chain')) `sc) "unsupported" "BAD")}")
2267− (crip "tag-nest-ford-collision: {(show-result (read-named %outer %tag-nest-middle nest-collision))}")
2268− (crip "tag-self: {(show-result (sample %tag-self))}")
2269− (crip "tag-self-tail: {(show-result (sample %tag-self-tail))}")
2270− (crip "tag-self-duplicate: {(show-result (sample %tag-self-duplicate))}")
2271− (crip "tag-self-hidden: {(show-result (sample %tag-self-hidden))}")
2272− (crip "tag-self-indirect: {(show-result (sample %tag-self-indirect))}")
2273− (crip "tag-mutual-a: {(show-result (sample %tag-mutual-a))}")
2274− (crip "tag-mutual-b: {(show-result (sample %tag-mutual-b))}")
2275− (crip "tag-self-pair: {(show-result (sample %tag-self-pair))}")
2276− (crip "tag-self-ford-collision: {(show-result (read-named %child %tag-self self-collision))}")
2277− (crip "tag-self-wrong-core: {(show-result (read-mold-in %other %tag-self (~(play ut sc) (ream '*tag-self')) self-other))}")
2278− (crip "tag-flat-large: {?:(&(?=(~ (safe-source-name-mode %tag-fuel-7 sc ~ 256 |)) ?=(^ (safe-source-name-mode %tag-fuel-7 sc ~ 4.096 |)) ?=([%& *] (sample %tag-flat-large))) "supported above 256" "BAD")}")
2279− (crip "tag-null-good: {(show-result (sample %tag-null-good))}")
2280− (crip "tag-null-duplicate: {(show-result (sample %tag-null-duplicate))}")
2281− (crip "tag-null-hidden: {(show-result (sample %tag-null-hidden))}")
2282− (crip "tag-valid: {(show-result (sample %tag-valid))}")
2283− (crip "tag-duplicate: {(show-result (sample %tag-duplicate))}")
2284− (crip "tag-collapsed: {(show-result (sample %tag-collapsed))}")
2285− (crip "tag-invalid-direct: {(show-result (sample %tag-invalid-direct))}")
2286− (crip "tag-invalid-alias: {(show-result (sample %tag-invalid-alias))}")
2287− (crip "tag-invalid-list: {(show-result (sample %tag-invalid-list))}")
2288− (crip "tag-enum-good: {(show-result (sample %tag-enum-good))}")
2289− (crip "tag-enum-bad: {(show-result (sample %tag-enum-bad))}")
2290− (crip "tag-nested-good: {(show-result (sample %tag-nested-good))}")
2291− (crip "tag-shadow-jar: {(show-result (read-named %shadow-static %tag-shadow-jar xc))}")
2292− (crip "tag-shadow-jug: {(show-result (read-named %shadow-static %tag-shadow-jug xc))}")
2293− (crip "tag-fuel-small: {?:(?=(^ (safe-source-name %tag-fuel-2 sc ~ 64)) "yes" "no")}")
2294− (crip "tag-fuel-large: {?:(?=(~ (safe-source-name %tag-fuel-11 sc ~ 64)) "rejected" "wrong")}")
2295− (crip "presence-action-1: {(show-result (present %action-1))}")
2296− (crip "presence-command-1: {(show-result (present %command-1))}")
2297− (crip "presence-update-1: {(show-result (present %update-1))}")
2298− (crip "presence-response-1: {(show-result (present %response-1))}")
2299− (crip "presence-topic: {(show-result (present %topic))}")
2300− (crip "presence-timing: {(show-result (present %timing))}")
2301− (crip "presence-places: {(show-result (present %places))}")
2302− (crip "docs-ent: {(show-result (docs-type %ent))}")
2303− (crip "docs-nud: {(show-result (docs-type %nud))}")
2304− (crip "tlon-saga: {(show-result (tlon %saga))}")
2305− (crip "tlon-epic: {(show-result (tlon %epic))}")
2306− ==
2307−
2308--
1765--
jibb-dev/lib/jibb.hoon+1707−493
@@ -63,8 +63,8 @@
63:: finds each node's end from the tokens alone, matching each opener
63:: finds each node's end from the tokens alone, matching each opener
64:: with its closer on the line, so a node that stops at a child where
64:: with its closer on the line, so a node that stops at a child where
65:: its closer follows fails it, and +check-spans-test plants such
65:: its closer follows fails it, and +check-spans-test plants such
66−:: wrong ends to show that it does (tools/hoon check-spans-test prints
66+:: wrong ends to show that it does (the jibb-check-spans test suite
67−:: the empty list, <<>>, when it passes).
67+:: runs it).
68::
68::
69:: ===================================================================
69:: ===================================================================
70:: 2. The layout pass (+layout)
70:: 2. The layout pass (+layout)
@@ -206,9 +206,11 @@
206:: token holds the text after @. An aura starting @s or
206:: token holds the text after @. An aura starting @s or
207:: @r is an error at 2nd: "signed and floating-point
207:: @r is an error at 2nd: "signed and floating-point
208:: auras are left out of Jibb"
208:: auras are left out of Jibb"
209−:: A-Z type variable: one capital. A letter or digit right
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 -
210−:: after it is an error there, "a type variable is one
212+:: is an error there, "a type variable is a capital,
211−:: capital letter", after the type variable's token
213+:: then lowercase letters and digits"
212:: a-z name [a-z][a-z0-9-]*, or a wing: two or more names
214:: a-z name [a-z][a-z0-9-]*, or a wing: two or more names
213:: joined by dots. Right after the name or wing, which
215:: joined by dots. Right after the name or wing, which
214:: is emitted first, a capital or _ is an error there,
216:: is emitted first, a capital or _ is an error there,
@@ -405,6 +407,7 @@
405:: Why: after the layout pass the grammar is LL(2). Each choice is made by
407:: Why: after the layout pass the grammar is LL(2). Each choice is made by
406:: the next token, at most with the one after it and whether it is tight:
408:: the next token, at most with the one after it and whether it is tight:
407:: name, then = tight a face (items, lines, fields, samples)
409:: name, then = tight a face (items, lines, fields, samples)
410+:: wing, then = tight a change's item or line, wing=value
408:: name, then + tight a pair
411:: name, then + tight a pair
409:: name or wing, then ( tight a change
412:: name or wing, then ( tight a change
410:: |=, then a term tight a constructor; else, where an
413:: |=, then a term tight a constructor; else, where an
@@ -412,6 +415,9 @@
412:: ++ or +$ a definition; else a body's final expr
415:: ++ or +$ a definition; else a body's final expr
413:: INDENT a body, an open bracket's lines, arms
416:: INDENT a body, an open bracket's lines, arms
414:: or cases; else the expression goes on
417:: 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
415:: So the parser never backtracks, its first failure is its furthest, and
421:: So the parser never backtracks, its first failure is its furthest, and
416:: "expected X, found Y" falls out of each arm without tracking failures
422:: "expected X, found Y" falls out of each arm without tracking failures
417:: across alternatives. Hoon's combinators read tapes of characters and
423:: across alternatives. Hoon's combinators read tapes of characters and
@@ -455,7 +461,9 @@
455:: cases below -> %mold; one case is that mold, several
461:: cases below -> %mold; one case is that mold, several
456:: are %union. The optional generic wraps either in %generic.
462:: are %union. The optional generic wraps either in %generic.
457:: ++ name expr or body -> %value (a body becomes a %body expr)
463:: ++ 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)
459:: call one operand is that operand; more -> %call head args
467:: call one operand is that operand; more -> %call head args
460:: operand literal -> %lit or %str; pathlit -> %path, as a path
468:: operand literal -> %lit or %str; pathlit -> %path, as a path
461:: literal is an expression (Decisions); !! -> %crash, as
469:: literal is an expression (Decisions); !! -> %crash, as
@@ -472,7 +480,9 @@
472:: that line, as () is no group. A ( followed by a rune is
480:: that line, as () is no group. A ( followed by a rune is
473:: the closed form. Lines of an open group or list take no
481:: the closed form. Lines of an open group or list take no
474:: name= (doc question)
482:: 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=
476:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch.
486:: rune |= -> %gate; ^- -> %cast; ~& -> %trace; ?- -> %branch.
477:: !! is an operand, not a rune (Decisions): alone where an
487:: !! is an operand, not a rune (Decisions): alone where an
478:: expression goes it is a call of one operand, and !! a
488:: expression goes it is a call of one operand, and !! a
@@ -553,7 +563,23 @@
553:: - Local definitions: at the start of any body, a gate's, an arm's,
563:: - Local definitions: at the start of any body, a gate's, an arm's,
554:: a ^-'s, a ~&'s or a ++'s, as the EBNF's body takes them
564:: a ^-'s, a ~&'s or a ++'s, as the EBNF's body takes them
555:: (Decisions); +$ as well as ++, as the Runes prose's "likewise"
565:: (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.
557:: - Where errors point: the doc says only "line, column and an
583:: - Where errors point: the doc says only "line, column and an
558:: excerpt"; 2.0 and Errors below say where.
584:: excerpt"; 2.0 and Errors below say where.
559::
585::
@@ -604,11 +630,12 @@
604:: found the end of the line" (+fail-space). No later line can give
630:: found the end of the line" (+fail-space). No later line can give
605:: a tight form its next token. A wing and a ( after a space are no
631:: a tight form its next token. A wing and a ( after a space are no
606:: error: that is a call; nor is / or %/ alone, a whole path. A
632:: 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
633+:: change's item is name= or wing=, so a name or a wing there with
608−:: fails just past the name, whatever follows: `m(b c)` at the
634+:: no = right after it fails just past it, whatever follows: `m(b c)`
609−:: space, `m(b)` at the ), `m(a"x)` at the " with the layout pass's
635+:: and `m(a.b 1)` at the space, `m(b)` at the ), `m(a"x)` at the "
610−:: message after the parser's (+unnamed, +moved). `m(a==1)` has its
636+:: with the layout pass's message after the parser's (+unnamed,
611−:: =, and fails at the second, where the layout pass does.
637+:: +moved). `m(a==1)` has its =, and fails at the second, where the
638+:: layout pass does.
612:: - Where the place needs text on its own line and the line ends,
639:: - Where the place needs text on its own line and the line ends,
613:: whatever line comes next: at the end of that line, just past its
640:: whatever line comes next: at the end of that line, just past its
614:: last token, "found the end of the line" (+fail-line), as no later
641:: last token, "found the end of the line" (+fail-line), as no later
@@ -786,7 +813,9 @@
786:: (value 8:1 init
813:: (value 8:1 init
787:: (cast 8:9
814:: (cast 8:9
788:: (ref 8:12 state)
815:: (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)))))
790:: (value 9:1 update
819:: (value 9:1 update
791:: (gate 9:11
820:: (gate 9:11
792:: (cell 9:14
821:: (cell 9:14
@@ -795,17 +824,17 @@
795:: (body 10:3
824:: (body 10:3
796:: (branch 10:3
825:: (branch 10:3
797:: (wing 10:6 a)
826:: (wing 10:6 a)
798−:: (arm 11:5
827+:: (arm 11:3
799−:: (cell 11:5 (lit 11:6 %add) (bind 11:11 item))
828+:: (cell 11:3 (lit 11:4 %add) (bind 11:9 item))
800−:: (change 11:18 s
829+:: (change 11:16 s
801−:: (edit 11:20 items
830+:: (edit 11:18 items
802−:: (tuple 11:26 (wing 11:27 item) (wing 11:32 items.s)))))
831+:: (tuple 11:24 (wing 11:25 item) (wing 11:30 items.s)))))
803−:: (arm 12:5
832+:: (arm 12:3
804−:: (lit 12:5 %toggle)
833+:: (lit 12:3 %toggle)
805−:: (change 12:18 s
834+:: (change 12:16 s
806−:: (edit 12:20 open
835+:: (edit 12:18 open
807−:: (group 12:25
836+:: (group 12:23
808−:: (call 12:26 (wing 12:26 not) (wing 12:30 open.s)))))))))))
837+:: (call 12:24 (wing 12:24 not) (wing 12:28 open.s)))))))))))
809::
838::
810:: 4.3 Errors (+show-error): "<file>:<line>:<col>: <message>", then the
839:: 4.3 Errors (+show-error): "<file>:<line>:<col>: <message>", then the
811:: source line, then a caret under the column (col - 1 spaces, then ^).
840:: source line, then a caret under the column (col - 1 spaces, then ^).
@@ -816,9 +845,9 @@
816:: prints as a space, so the caret stays under its column and golden
845:: prints as a space, so the caret stays under its column and golden
817:: files hold no raw control bytes.
846:: files hold no raw control bytes.
818::
847::
819−:: /ui/basket.jibb:22:5: msg has no case %submitt
848+:: /ui/basket.jibb:22:3: msg has no case %submitt
820−:: %submitt [m(note="") ~]
849+:: %submitt [m(note="") ~]
821−:: ^
850+:: ^
822::
851::
823|%
852|%
824+| %positions
853+| %positions
@@ -964,9 +993,10 @@
964::
993::
965+$ item $~([*span ~ *expr] [at=span face=(unit term) val=expr])
994+$ item $~([*span ~ *expr] [at=span face=(unit term) val=expr])
966::
995::
967−:: +edit: a change's item or line, name=value
996+:: +edit: a change's item or line, name=value or wing=value; names
997+:: as written, as a %wing's: open.cart is ~[%open %cart]
968::
998::
969−+$ edit $~([*span %$ *expr] [at=span name=term val=expr])
999++$ edit $~([*span ~ *expr] [at=span names=(list term) val=expr])
970::
1000::
971:: +arm: a ?- arm, a pattern and an expression or body
1001:: +arm: a ?- arm, a pattern and an expression or body
972::
1002::
@@ -1355,10 +1385,10 @@
1355 =? n &(?=(^ rest) (is-upper i.rest)) +(n)
1385 =? n &(?=(^ rest) (is-upper i.rest)) +(n)
1356 (emit +(n) [%aura (@ta (crip (scag n t.cs)))])
1386 (emit +(n) [%aura (@ta (crip (scag n t.cs)))])
1357 ?: (is-upper a)
1387 ?: (is-upper a)
1388+ =/ n=@ud (run-len t.cs tvar-mask)
1358− => (emit 1 [%tvar a])
1389+ => (emit +(n) [%tvar (crip [a (scag n t.cs)])])
1359− ?. &(?=(^ cs) |((is-lower i.cs) (is-upper i.cs) (is-digit i.cs)))
1390+ ?. &(?=(^ cs) |((is-upper i.cs) =('_' i.cs) =('-' i.cs))) cor
1360− cor
1361− (err col "a type variable is one capital letter")
1391+ (err col "a type variable is a capital, then lowercase letters and digits")
1362 ?: =(':' a)
1392 ?: =(':' a)
1363 ?. =(0 dep) (err col "a comment can't start inside `\{…}`")
1393 ?. =(0 dep) (err col "a comment can't start inside `\{…}`")
1364 ?: =(':' b) comment
1394 ?: =(':' b) comment
@@ -1662,6 +1692,7 @@
1662++ digit-mask 0x3ff.0000.0000.0000 :: 0-9
1692++ digit-mask 0x3ff.0000.0000.0000 :: 0-9
1663++ hex-mask 0x7e.0000.0000.03ff.0000.0000.0000 :: 0-9 a-f
1693++ hex-mask 0x7e.0000.0000.03ff.0000.0000.0000 :: 0-9 a-f
1664++ name-mask 0x7ff.fffe.0000.0000.03ff.2000.0000.0000 :: a-z 0-9 -
1694++ name-mask 0x7ff.fffe.0000.0000.03ff.2000.0000.0000 :: a-z 0-9 -
1695+++ tvar-mask 0x7ff.fffe.0000.0000.03ff.0000.0000.0000 :: a-z 0-9
1665++ knot-mask 0x47ff.fffe.8000.0000.03ff.6000.0000.0000 :: and . ~ _
1696++ knot-mask 0x47ff.fffe.8000.0000.03ff.6000.0000.0000 :: and . ~ _
1666++ number-mask 0x7ff.fffe.07ff.fffe.03ff.4000.0000.0000 :: a-z A-Z 0-9 .
1697++ number-mask 0x7ff.fffe.07ff.fffe.03ff.4000.0000.0000 :: a-z A-Z 0-9 .
1667++ bad-mask 0x8000.0000.0000.0000.0000.0000.ffff.fbff :: 2.2
1698++ bad-mask 0x8000.0000.0000.0000.0000.0000.ffff.fbff :: 2.2
@@ -2280,7 +2311,7 @@
2280++ sexp-edit
2311++ sexp-edit
2281 |= e=edit
2312 |= e=edit
2282 ^- sexp
2313 ^- sexp
2283− (nod "edit" at.e (trip name.e) ~[(sexp-expr val.e)])
2314+ (nod "edit" at.e (show-names names.e) ~[(sexp-expr val.e)])
2284::
2315::
2285++ sexp-arm
2316++ sexp-arm
2286 |= a=arm
2317 |= a=arm
@@ -2689,24 +2720,32 @@
2689 ?~ t.els i.els
2720 ?~ t.els i.els
2690 [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
2721 [%call [beg:(span-of i.els) end:(span-of (rear t.els))] i.els t.els]
2691::
2722::
2723+:: +slot: a bracket's item or line as read, before +bracket-node
2724+:: makes it an item or an edit: its name=, or a change's wing=, else ~
2725+::
2726++$ slot [at=span face=(list term) val=expr]
2727+::
2692:: +bracket-node: a tuple, list or change from its items, ending at fin
2728:: +bracket-node: a tuple, list or change from its items, ending at fin
2693::
2729::
2694++ bracket-node
2730++ bracket-node
2695 |= $: kind=?(%tuple %list %change)
2731 |= $: kind=?(%tuple %list %change)
2696 op=token
2732 op=token
2697 target=(unit [t=token names=(list term)])
2733 target=(unit [t=token names=(list term)])
2698− its=(list item)
2734+ its=(list slot)
2699 fin=loc
2735 fin=loc
2700 ==
2736 ==
2701 ^- expr
2737 ^- expr
2702 ?- kind
2738 ?- kind
2739+ %tuple
2703− %tuple [%tuple [beg.at.op fin] its]
2740+ :+ %tuple [beg.at.op fin]
2704− %list [%list [beg.at.op fin] (turn its |=(i=item val.i))]
2741+ (turn its |=(i=slot ^-(item [at.i ?~(face.i ~ `i.face.i) val.i])))
2742+ ::
2743+ %list [%list [beg.at.op fin] (turn its |=(i=slot val.i))]
2705 ::
2744 ::
2706 %change
2745 %change
2707 =/ beg=loc ?~(target beg.at.op beg.at.t.u.target)
2746 =/ beg=loc ?~(target beg.at.op beg.at.t.u.target)
2708 :^ %change [beg fin] ?~(target ~ names.u.target)
2747 :^ %change [beg fin] ?~(target ~ names.u.target)
2709− (turn its |=(i=item ^-(edit [at.i ?~(face.i %$ u.face.i) val.i])))
2748+ (turn its |=(i=slot ^-(edit [at.i face.i val.i])))
2710 ==
2749 ==
2711::
2750::
2712+| %parser
2751+| %parser
@@ -2927,23 +2966,22 @@
2927 ::
2966 ::
2928 :: +unnamed: a change's item or line without its name=
2967 :: +unnamed: a change's item or line without its name=
2929 ::
2968 ::
2930− :: A name could still begin one, so the error is just past it, as
2969+ :: A name or a wing could still begin one, so the error is just
2931− :: a tight form's is (+fail-space): `m(b c)` at the space, `m(b)`
2970+ :: past it, as a tight form's is (+fail-space): `m(b c)` and
2932− :: at the ). So is an error token's text there, unless it begins
2971+ :: `m(a.b 1)` at the space, `m(b)` at the ). So is an error token's
2933− :: with the =: `m(a"x)` at the ", with the layout pass's message
2972+ :: text there, unless it begins with the =: `m(a"x)` at the ", with
2934− :: after the parser's (+moved), but `m(a==1)` at the lexer's error,
2973+ :: the layout pass's message after the parser's (+moved), but
2935− :: the second =. So is a wing's first name: `m(a.b=1)` fails at the
2974+ :: `m(a==1)` at the lexer's error, the second =. At an error token
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).
2975+ :: whose text can't begin a name, at that text, as `m( @sd` at the
2976+ :: @ (+fail-in).
2938 ::
2977 ::
2939 ++ unnamed
2978 ++ unnamed
2940 |= ts=(list token)
2979 |= ts=(list token)
2941 ^- [%| p=error]
2980 ^- [%| p=error]
2942 =/ why=tape "a change's items are named, as in m(done=%.y)"
2981 =/ why=tape "a change's items are named, as in m(done=%.y)"
2943 ?: ?=([[* * [%error *]] *] ts) (bad-in ts "a named item" lower-mask)
2982 ?: ?=([[* * [%error *]] *] ts) (bad-in ts "a named item" lower-mask)
2944− ?: ?=([[* * [%wing *]] *] ts)
2983+ ?. ?=([[* * ?([%name *] [%wing *])] *] ts)
2945− (bad-in-why ts "a named item" lower-mask why)
2946− ?. ?=([[* * [%name *]] *] ts) (bad-why ts "a named item" why)
2984+ (bad-why ts "a named item" why)
2947 =/ want=tape "`=` right after {(show-found i.ts)}"
2985 =/ want=tape "`=` right after {(show-found i.ts)}"
2948 ?: ?& ?=([* [* * [%error *]] *] ts)
2986 ?: ?& ?=([* [* * [%error *]] *] ts)
2949 =(end.at.i.ts from.lex.i.t.ts)
2987 =(end.at.i.ts from.lex.i.t.ts)
@@ -2961,9 +2999,10 @@
2961 :: closes on its line (2.9). A bracket that needs none of these
2999 :: closes on its line (2.9). A bracket that needs none of these
2962 :: closes with the deeper lines instead (+shut). No later line can
3000 :: closes with the deeper lines instead (+shut). No later line can
2963 :: give it that, so the error is at the end of the line that took
3001 :: 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
3002+ :: them (section 3, Errors). want is what it needs. It looks only when
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.
3003+ :: after begins with NEWLINE or DEDENT, so it costs nothing on the way
3004+ :: to a tree, except where a rune takes the rest of a body (+read-last):
3005+ :: a look at that rune's line.
2967 ::
3006 ::
2968 ++ doomed
3007 ++ doomed
2969 |= [ts=(list token) after=(list token) want=tape]
3008 |= [ts=(list token) after=(list token) want=tape]
@@ -3120,7 +3159,7 @@
3120 ?: =(%'++' lex.rune)
3159 ?: =(%'++' lex.rune)
3121 ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
3160 ;< [nam=term after=(list token)] then (read-def-name rune t.ts)
3122 ;< [e=expr more=(list token)] then
3161 ;< [e=expr more=(list token)] then
3123− (read-expr-or-body "the name" after)
3162+ (read-expr-or-body | "the name" after)
3124 [%& [%value [beg.at.rune end:(span-of e)] nam e] more]
3163 [%& [%value [beg.at.rune end:(span-of e)] nam e] more]
3125 ?: (is-closer rune)
3164 ?: (is-closer rune)
3126 %^ bad-why ts "a definition"
3165 %^ bad-why ts "a definition"
@@ -3200,20 +3239,36 @@
3200 [%& p.lex.i.ts t.ts]
3239 [%& p.lex.i.ts t.ts]
3201 ::
3240 ::
3202 :: +read-expr-or-body: a space and an expression on the line, or a
3241 :: +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
3242+ :: body on deeper lines; what names what comes before, for errors.
3243+ :: On a body's final line (fin, +read-last), a line at the same depth
3244+ :: is the rest of the body instead, and the expression on the line
3245+ :: goes on with fin, except a ?-, which keeps its arms deeper
3204 ::
3246 ::
3205 ++ read-expr-or-body
3247 ++ read-expr-or-body
3206− |= [what=tape ts=(list token)]
3248+ |= [fin=? what=tape ts=(list token)]
3207 ^- (pare expr)
3249 ^- (pare expr)
3208 ?: ?=([[* * %indent] *] ts) (read-body t.ts)
3250 ?: ?=([[* * %indent] *] ts) (read-body t.ts)
3251+ ?: &(fin ?=([[* * %newline] *] ts)) (read-rest t.ts)
3209 ?: ?=([[* * ?(%newline %dedent)] *] ts)
3252 ?: ?=([[* * ?(%newline %dedent)] *] ts)
3210 (bad ts "an expression, or a body on deeper lines")
3253 (bad ts "an expression, or a body on deeper lines")
3211 ?: &(?=(^ ts) tight.i.ts) (no-gap ts "a space after {what}")
3254 ?: &(?=(^ ts) tight.i.ts) (no-gap ts "a space after {what}")
3212− (read-expr ts)
3255+ (read-last &(fin !?=([[* * %'?-'] *] ts)) ts)
3213 ::
3256 ::
3214− :: +read-body: after its INDENT, { definition NEWLINE } expr DEDENT
3257+ :: +read-body: after its INDENT, the rest of a body, then its DEDENT
3215 ::
3258 ::
3216 ++ read-body
3259 ++ read-body
3260+ |= ts=(list token)
3261+ ^- (pare expr)
3262+ ;< [e=expr after=(list token)] then (read-rest ts)
3263+ ?> ?=([[* * %dedent] *] after)
3264+ [%& e t.after]
3265+ ::
3266+ :: +read-rest: { definition NEWLINE } last, up to the DEDENT that ends
3267+ :: a body, which it leaves for whatever opened the body: its INDENT's
3268+ :: reader, or the rune on the final line that took the rest of it
3269+ :: (+read-last)
3270+ ::
3271+ ++ read-rest
3217 |= ts=(list token)
3272 |= ts=(list token)
3218 ^- (pare expr)
3273 ^- (pare expr)
3219 =| defs=(list def)
3274 =| defs=(list def)
@@ -3227,12 +3282,15 @@
3227 %: bad-in-why ts "a definition or an expression" plus-mask
3282 %: bad-in-why ts "a definition or an expression" plus-mask
3228 "`+` begins `++` or `+$`"
3283 "`+` begins `++` or `+$`"
3229 ==
3284 ==
3230− ;< [e=expr after=(list token)] then (read-expr ts)
3285+ ;< [e=expr after=(list token)] then (read-last & ts)
3231 ?: ?=([[* * %dedent] *] after)
3286 ?: ?=([[* * %dedent] *] after)
3232 =/ ds=(list def) (flop defs)
3287 =/ ds=(list def) (flop defs)
3233 =/ beg=loc ?~(ds beg:(span-of e) beg:(span-of i.ds))
3288 =/ beg=loc ?~(ds beg:(span-of e) beg:(span-of i.ds))
3234− [%& [%body [beg end:(span-of e)] ds e] t.after]
3289+ [%& [%body [beg end:(span-of e)] ds e] after]
3235 ?. ?=([[* * %newline] *] after) (bad-end-in after (tail-can e))
3290 ?. ?=([[* * %newline] *] after) (bad-end-in after (tail-can e))
3291+ ?: &(?=(%branch -.e) !?=([* [* * ?(%'++' %'+$')] *] after))
3292+ %^ bad-why after "the end of the body"
3293+ "this `?-`'s arms are on deeper lines, so this one goes there too"
3236 %^ bad-why after "the end of the body"
3294 %^ bad-why after "the end of the body"
3237 "a body's final expression is its last line"
3295 "a body's final expression is its last line"
3238 ::
3296 ::
@@ -3241,13 +3299,24 @@
3241 ++ read-expr
3299 ++ read-expr
3242 |= ts=(list token)
3300 |= ts=(list token)
3243 ^- (pare expr)
3301 ^- (pare expr)
3302+ (read-last | ts)
3303+ ::
3304+ :: +read-last: +read-expr, where fin says the expression is a body's
3305+ :: final line or goes on one, with no bracket open before it: then
3306+ :: the rune that ends the line may take the rest of the body at the
3307+ :: same depth as its last child, and a ?- that begins the line its
3308+ :: arms (section 3, The rest of a body)
3309+ ::
3310+ ++ read-last
3311+ |= [fin=? ts=(list token)]
3312+ ^- (pare expr)
3244 ?~ ts (bad ts "an expression")
3313 ?~ ts (bad ts "an expression")
3245 =* t i.ts
3314 =* t i.ts
3246 ?+ lex.t (read-call ts)
3315 ?+ lex.t (read-call ts)
3247− %'|=' ?:((is-ctor ts) (read-call ts) (read-gate t t.ts))
3316+ %'|=' ?:((is-ctor ts) (read-call ts) (read-gate fin t t.ts))
3248− %'^-' (read-cast t t.ts)
3317+ %'^-' (read-cast fin t t.ts)
3249− %'~&' (read-trace t t.ts)
3318+ %'~&' (read-trace fin t t.ts)
3250− %'?-' (read-branch t t.ts)
3319+ %'?-' (read-branch fin t t.ts)
3251 ==
3320 ==
3252 ::
3321 ::
3253 :: +read-call: operand { operand }; one operand alone is itself
3322 :: +read-call: operand { operand }; one operand alone is itself
@@ -3462,9 +3531,9 @@
3462 (unclosed par ")" after)
3531 (unclosed par ")" after)
3463 ;< [els=(list expr) after=(list token)] then (read-operands ts)
3532 ;< [els=(list expr) after=(list token)] then (read-operands ts)
3464 ?: ?=([[* * %indent] *] after)
3533 ?: ?=([[* * %indent] *] after)
3465− ;< [ls=(list item) more=(list token)] then
3534+ ;< [ls=(list slot) more=(list token)] then
3466 (read-lines %group t.after)
3535 (read-lines %group t.after)
3467− =/ inner=expr (call-of (weld els (turn ls |=(i=item val.i))))
3536+ =/ inner=expr (call-of (weld els (turn ls |=(i=slot val.i))))
3468 [%& [%group [beg.at.par end:(span-of inner)] inner] more]
3537 [%& [%group [beg.at.par end:(span-of inner)] inner] more]
3469 ?~ els
3538 ?~ els
3470 ?: ?=([[* * ?(%newline %dedent)] *] after)
3539 ?: ?=([[* * ?(%newline %dedent)] *] after)
@@ -3489,7 +3558,7 @@
3489 ==
3558 ==
3490 ^- (pare expr)
3559 ^- (pare expr)
3491 =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
3560 =/ close=?(%')' %']') ?:(?=(%change kind) %')' %']')
3492− =| its=(list item)
3561+ =| its=(list slot)
3493 |- ^- (pare expr)
3562 |- ^- (pare expr)
3494 ?~ ts (bad ts "an item")
3563 ?~ ts (bad ts "an item")
3495 =* t i.ts
3564 =* t i.ts
@@ -3497,8 +3566,8 @@
3497 [%& (bracket-node kind op target (flop its) end.at.t) t.ts]
3566 [%& (bracket-node kind op target (flop its) end.at.t) t.ts]
3498 ?: (is-closer t) (unclosed op (trip close) ts)
3567 ?: (is-closer t) (unclosed op (trip close) ts)
3499 ?: ?=(%indent lex.t)
3568 ?: ?=(%indent lex.t)
3500− ;< [ls=(list item) more=(list token)] then (read-lines kind t.ts)
3569+ ;< [ls=(list slot) more=(list token)] then (read-lines kind t.ts)
3501− =/ every=(list item) (weld (flop its) ls)
3570+ =/ every=(list slot) (weld (flop its) ls)
3502 =/ fin=loc ?~(every end.at.op end.at:(rear every))
3571 =/ fin=loc ?~(every end.at.op end.at:(rear every))
3503 [%& (bracket-node kind op target every fin) more]
3572 [%& (bracket-node kind op target every fin) more]
3504 ?: &(?=(^ its) (shut op `at.i.its ts))
3573 ?: &(?=(^ its) (shut op `at.i.its ts))
@@ -3506,21 +3575,21 @@
3506 ?: ?=(?(%newline %dedent) lex.t)
3575 ?: ?=(?(%newline %dedent) lex.t)
3507 (unclosed-open op (trip close) "an item" ts)
3576 (unclosed-open op (trip close) "an item" ts)
3508 ?: &(tight.t ?=(^ its)) (no-space ts)
3577 ?: &(tight.t ?=(^ its)) (no-space ts)
3509− ;< [i=item more=(list token)] then (read-item kind ts)
3578+ ;< [i=slot more=(list token)] then (read-item kind ts)
3510 $(its [i its], ts more)
3579 $(its [i its], ts more)
3511 ::
3580 ::
3512 :: +read-item: [ name= ] operand; a tuple's item may be named, a
3581 :: +read-item: [ name= ] operand; a tuple's item may be named, a
3513− :: change's must be, a list's is not
3582+ :: change's must be, by a name or a wing, a list's is not
3514 ::
3583 ::
3515 ++ read-item
3584 ++ read-item
3516 |= [kind=?(%tuple %list %change) ts=(list token)]
3585 |= [kind=?(%tuple %list %change) ts=(list token)]
3517− ^- (pare item)
3586+ ^- (pare slot)
3518− ?: &(!?=(%list kind) ?=([[* * [%name *]] [* %& %'='] *] ts))
3587+ ?: &(?=([* * *] ts) (named-item kind ts))
3519 =* nam i.ts
3588 =* nam i.ts
3520 =/ rest=(list token) t.t.ts
3589 =/ rest=(list token) t.t.ts
3521 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3590 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3522 ;< [v=expr after=(list token)] then (read-operand rest)
3591 ;< [v=expr after=(list token)] then (read-operand rest)
3523− [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3592+ [%& [[beg.at.nam end:(span-of v)] (names-of lex.nam) v] after]
3524 ?: ?=(%change kind) (unnamed ts)
3593 ?: ?=(%change kind) (unnamed ts)
3525 ?: &(?=(^ ts) (is-rune i.ts))
3594 ?: &(?=(^ ts) (is-rune i.ts))
3526 %: bad-in-why ts "an expression" operand-mask
3595 %: bad-in-why ts "an expression" operand-mask
@@ -3529,15 +3598,25 @@
3529 ;< [v=expr after=(list token)] then (read-operand ts)
3598 ;< [v=expr after=(list token)] then (read-operand ts)
3530 [%& [(span-of v) ~ v] after]
3599 [%& [(span-of v) ~ v] after]
3531 ::
3600 ::
3601+ :: +named-item: whether ts begins an item's or a line's name=: a
3602+ :: tuple's or a change's name, or a change's wing, then = tight
3603+ ::
3604+ ++ named-item
3605+ |= [kind=?(%tuple %list %change %group) ts=(list token)]
3606+ ^- ?
3607+ ?. ?=([* [* %& %'='] *] ts) |
3608+ ?: ?=([[* * [%name *]] *] ts) ?=(?(%tuple %change) kind)
3609+ &(?=(%change kind) ?=([[* * [%wing *]] *] ts))
3610+ ::
3532 :: +read-lines: after an open bracket's INDENT, its lines, an item
3611 :: +read-lines: after an open bracket's INDENT, its lines, an item
3533 :: each, to its DEDENT
3612 :: each, to its DEDENT
3534 ::
3613 ::
3535 ++ read-lines
3614 ++ read-lines
3536 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3615 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3537− ^- (pare (list item))
3616+ ^- (pare (list slot))
3538− =| ls=(list item)
3617+ =| ls=(list slot)
3539− |- ^- (pare (list item))
3618+ |- ^- (pare (list slot))
3540− ;< [l=item after=(list token)] then (read-line kind ts)
3619+ ;< [l=slot after=(list token)] then (read-line kind ts)
3541 ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
3620 ?: ?=([[* * %newline] *] after) $(ls [l ls], ts t.after)
3542 ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
3621 ?: ?=([[* * %dedent] *] after) [%& (flop [l ls]) t.after]
3543 ?. ?=([[* * ?(%')' %']')] *] after) (bad-end-in after (tail-can val.l))
3622 ?. ?=([[* * ?(%')' %']')] *] after) (bad-end-in after (tail-can val.l))
@@ -3564,22 +3643,20 @@
3564 "its items end at the first line that isn't deeper"
3643 "its items end at the first line that isn't deeper"
3565 ::
3644 ::
3566 :: +read-line: an open bracket's line, [ name= ] expr; a tuple's may
3645 :: +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
3646+ :: be named, a change's must be, by a name or a wing, a list's and a
3568− :: (doc question)
3647+ :: group's are not (doc question)
3569 ::
3648 ::
3570 ++ read-line
3649 ++ read-line
3571 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3650 |= [kind=?(%tuple %list %change %group) ts=(list token)]
3572− ^- (pare item)
3651+ ^- (pare slot)
3573 =/ cf (closer-first ts "an item")
3652 =/ cf (closer-first ts "an item")
3574 ?^ cf u.cf
3653 ?^ cf u.cf
3575− ?: ?& ?=(?(%tuple %change) kind)
3654+ ?: &(?=([* * *] ts) (named-item kind ts))
3576− ?=([[* * [%name *]] [* %& %'='] *] ts)
3577− ==
3578 =* nam i.ts
3655 =* nam i.ts
3579 =/ rest=(list token) t.t.ts
3656 =/ rest=(list token) t.t.ts
3580 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3657 ?: |(?=(~ rest) !tight.i.rest) (bad-space i.t.ts rest "a value")
3581 ;< [v=expr after=(list token)] then (read-expr rest)
3658 ;< [v=expr after=(list token)] then (read-expr rest)
3582− [%& [[beg.at.nam end:(span-of v)] `p.lex.nam v] after]
3659+ [%& [[beg.at.nam end:(span-of v)] (names-of lex.nam) v] after]
3583 ?: ?=(%change kind) (unnamed ts)
3660 ?: ?=(%change kind) (unnamed ts)
3584 ;< [v=expr after=(list token)] then (read-expr ts)
3661 ;< [v=expr after=(list token)] then (read-expr ts)
3585 [%& [(span-of v) ~ v] after]
3662 [%& [(span-of v) ~ v] after]
@@ -3616,10 +3693,11 @@
3616 %^ bad-why more (closing op ")")
3693 %^ bad-why more (closing op ")")
3617 "the wide gate's body is one operand, so a call goes in parentheses"
3694 "the wide gate's body is one operand, so a call goes in parentheses"
3618 ::
3695 ::
3619− :: +read-gate: |= sample, then an expression or a body
3696+ :: +read-gate: |= sample, then an expression or a body; fin as for
3697+ :: +read-last
3620 ::
3698 ::
3621 ++ read-gate
3699 ++ read-gate
3622− |= [bar=token ts=(list token)]
3700+ |= [fin=? bar=token ts=(list token)]
3623 ^- (pare expr)
3701 ^- (pare expr)
3624 ?: &(?=(^ ts) tight.i.ts)
3702 ?: &(?=(^ ts) tight.i.ts)
3625 :: a % could begin a constructor's term, as |=%got
3703 :: a % could begin a constructor's term, as |=%got
@@ -3631,13 +3709,14 @@
3631 =/ dm (doomed ts after "an expression, or a body on deeper lines")
3709 =/ dm (doomed ts after "an expression, or a body on deeper lines")
3632 ?^ dm u.dm
3710 ?^ dm u.dm
3633 ;< [e=expr more=(list token)] then
3711 ;< [e=expr more=(list token)] then
3634− (read-expr-or-body "the sample" after)
3712+ (read-expr-or-body fin "the sample" after)
3635 [%& [%gate [beg.at.bar end:(span-of e)] s e] more]
3713 [%& [%gate [beg.at.bar end:(span-of e)] s e] more]
3636 ::
3714 ::
3637− :: +read-cast: ^- mold, then an expression or a body
3715+ :: +read-cast: ^- mold, then an expression or a body; fin as for
3716+ :: +read-last
3638 ::
3717 ::
3639 ++ read-cast
3718 ++ read-cast
3640− |= [ket=token ts=(list token)]
3719+ |= [fin=? ket=token ts=(list token)]
3641 ^- (pare expr)
3720 ^- (pare expr)
3642 ?: &(?=(^ ts) tight.i.ts) (wide-rune "^-" ts)
3721 ?: &(?=(^ ts) tight.i.ts) (wide-rune "^-" ts)
3643 ;< [s=shape after=(list token)] then (read-mold ts)
3722 ;< [s=shape after=(list token)] then (read-mold ts)
@@ -3646,41 +3725,65 @@
3646 =/ dm (doomed ts after "an expression, or a body on deeper lines")
3725 =/ dm (doomed ts after "an expression, or a body on deeper lines")
3647 ?^ dm u.dm
3726 ?^ dm u.dm
3648 ;< [e=expr more=(list token)] then
3727 ;< [e=expr more=(list token)] then
3649− (read-expr-or-body "the mold" after)
3728+ (read-expr-or-body fin "the mold" after)
3650 [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
3729 [%& [%cast [beg.at.ket end:(span-of e)] s e] more]
3651 ::
3730 ::
3652− :: +read-trace: ~& expr, then its body below
3731+ :: +read-trace: ~& expr, then its body below, or, on a body's final
3732+ :: line (fin, +read-last), the rest of the body
3653 ::
3733 ::
3654 ++ read-trace
3734 ++ read-trace
3655− |= [sig=token ts=(list token)]
3735+ |= [fin=? sig=token ts=(list token)]
3656 ^- (pare expr)
3736 ^- (pare expr)
3657 ?: &(?=(^ ts) tight.i.ts) (wide-rune "~&" ts)
3737 ?: &(?=(^ ts) tight.i.ts) (wide-rune "~&" ts)
3658 ;< [v=expr after=(list token)] then (read-expr ts)
3738 ;< [v=expr after=(list token)] then (read-expr ts)
3659− ?. ?=([[* * %indent] *] after)
3660− =/ dm (doomed ts after "`~&`'s body on deeper lines")
3739+ =/ dm (doomed ts after "`~&`'s body on deeper lines")
3661− ?^ dm u.dm
3740+ ?^ dm u.dm
3741+ ;< [b=expr more=(list token)] then
3742+ ?: ?=([[* * %indent] *] after) (read-body t.after)
3743+ ?: &(fin ?=([[* * %newline] *] after)) (read-rest t.after)
3662 (bad after "`~&`'s body on deeper lines")
3744 (bad after "`~&`'s body on deeper lines")
3663− ;< [b=expr more=(list token)] then (read-body t.after)
3664 [%& [%trace [beg.at.sig end:(span-of b)] v b] more]
3745 [%& [%trace [beg.at.sig end:(span-of b)] v b] more]
3665 ::
3746 ::
3666− :: +read-branch: ?- expr, then its arms below, one per line
3747+ :: +read-branch: ?- expr, then its arms below, one per line; or, when
3748+ :: it begins a body's final line (fin, +read-last), at its own depth
3749+ :: to the end of the body, whose DEDENT it leaves (+read-rest)
3667 ::
3750 ::
3668 ++ read-branch
3751 ++ read-branch
3669− |= [wut=token ts=(list token)]
3752+ |= [fin=? wut=token ts=(list token)]
3670 ^- (pare expr)
3753 ^- (pare expr)
3671 ?: &(?=(^ ts) tight.i.ts) (wide-rune "?-" ts)
3754 ?: &(?=(^ ts) tight.i.ts) (wide-rune "?-" ts)
3672 ;< [s=expr after=(list token)] then (read-expr ts)
3755 ;< [s=expr after=(list token)] then (read-expr ts)
3673− ?. ?=([[* * %indent] *] after)
3674− =/ dm (doomed ts after "`?-`'s arms on deeper lines")
3756+ =/ dm (doomed ts after "`?-`'s arms on deeper lines")
3675− ?^ dm u.dm
3757+ ?^ dm u.dm
3758+ ?. ?=([[* * ?(%indent %newline)] *] after)
3676 (bad after "`?-`'s arms on deeper lines")
3759 (bad after "`?-`'s arms on deeper lines")
3760+ =/ flat=? ?=(%newline lex.i.after)
3761+ ?: &(flat !fin) (bad after "`?-`'s arms on deeper lines")
3677 =| arms=(list arm)
3762 =| arms=(list arm)
3678 =/ rest=(list token) t.after
3763 =/ rest=(list token) t.after
3679 |- ^- (pare expr)
3764 |- ^- (pare expr)
3680− ;< [a=arm more=(list token)] then (read-arm rest)
3765+ ;< [a=arm more=(list token)] then
3766+ ?:(flat (read-flat-arm rest) (read-arm rest))
3681 ?: ?=([[* * %newline] *] more) $(arms [a arms], rest t.more)
3767 ?: ?=([[* * %newline] *] more) $(arms [a arms], rest t.more)
3682 ?. ?=([[* * %dedent] *] more) (bad-end-in more (tail-can val.a))
3768 ?. ?=([[* * %dedent] *] more) (bad-end-in more (tail-can val.a))
3683− [%& [%branch [beg.at.wut end.at.a] s (flop [a arms])] t.more]
3769+ =/ at=span [beg.at.wut end.at.a]
3770+ [%& [%branch at s (flop [a arms])] ?:(flat more t.more)]
3771+ ::
3772+ :: +read-flat-arm: +read-arm at its ?-'s depth, where a line that
3773+ :: could begin the body's other lines gets a hint
3774+ ::
3775+ ++ read-flat-arm
3776+ |= ts=(list token)
3777+ ^- (pare arm)
3778+ ?: ?=([[* * ?(%'++' %'+$')] *] ts)
3779+ %: bad-in-why ts "a pattern" pattern-mask
3780+ "a body's local definitions come before its final expression"
3781+ ==
3782+ ?: ?=([[* * ?(%'~&' %'^-')] *] ts)
3783+ %: bad-in-why ts "a pattern" pattern-mask
3784+ "a trace or cast goes in the arm's body"
3785+ ==
3786+ (read-arm ts)
3684 ::
3787 ::
3685 :: +read-arm: a pattern, then an expression or a body
3788 :: +read-arm: a pattern, then an expression or a body
3686 ::
3789 ::
@@ -3695,7 +3798,7 @@
3695 %^ bad-why after "a space after the pattern"
3798 %^ bad-why after "a space after the pattern"
3696 "patterns take no `name=`: a bare name binds, as [a b]"
3799 "patterns take no `name=`: a bare name binds, as [a b]"
3697 ;< [e=expr more=(list token)] then
3800 ;< [e=expr more=(list token)] then
3698− (read-expr-or-body "the pattern" after)
3801+ (read-expr-or-body | "the pattern" after)
3699 [%& [[beg:(span-of p) end:(span-of e)] p e] more]
3802 [%& [[beg:(span-of p) end:(span-of e)] p e] more]
3700 ::
3803 ::
3701 :: +read-pattern: a term, number, string, ship, loobean, ~, * or name,
3804 :: +read-pattern: a term, number, string, ship, loobean, ~, * or name,
@@ -4437,7 +4540,7 @@
4437++ outline-edit
4540++ outline-edit
4438 |= e=edit
4541 |= e=edit
4439 ^- outline
4542 ^- outline
4440− [%edit at.e ~[%name] %kid ~[(outline-expr val.e)]]
4543+ [%edit at.e ~[%name %wing] %kid ~[(outline-expr val.e)]]
4441::
4544::
4442++ outline-arm
4545++ outline-arm
4443 |= a=arm
4546 |= a=arm
@@ -4510,9 +4613,9 @@
4510::
4613::
4511:: Each case parses a source, checks that its spans pass, then moves
4614:: Each case parses a source, checks that its spans pass, then moves
4512:: the span of every node of a kind that starts at a place, as a
4615:: the span of every node of a kind that starts at a place, as a
4513−:: parser bug would, and checks that +check-spans says so. Run it as
4616+:: parser bug would, and checks that +check-spans says so.
4514−:: tools/hoon check-spans-test, which prints <<>> when every case
4617+:: tests/lib/jibb-check-spans.hoon runs it, under eval with
4515−:: passes.
4618+:: tools/test-arms and on the ship.
4516::
4619::
4517++ check-spans-test
4620++ check-spans-test
4518 ^- (list tape)
4621 ^- (list tape)
@@ -4614,7 +4717,10 @@
4614:: Restricted-number promotion considers written capitals only; if there
4717:: Restricted-number promotion considers written capitals only; if there
4615:: are none, it skips the otherwise unnecessary environment traversal.
4718:: are none, it skips the otherwise unnecessary environment traversal.
4616:: Bare @ is a separate unrestricted atom type. A directional fit check
4719:: 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
4720+:: permits concrete atoms to widen to it, never the reverse. A bare
4721+:: decimal is a @ud: its variable binds only @ud or @u, it fits @ and *,
4722+:: and +decimal-misfit names it where it meets another aura (S4); a
4723+:: ++ generic over its aura generalizes it to any aura. A fit that
4618:: needs a not-yet-implemented constraint remains unsupported. Named unions
4724:: needs a not-yet-implemented constraint remains unsupported. Named unions
4619:: retain origin and ordered arguments, including phantom arguments, apart
4725:: retain origin and ordered arguments, including phantom arguments, apart
4620:: from their display name. Generic cases must be disjoint for all arguments.
4726:: from their display name. Generic cases must be disjoint for all arguments.
@@ -4634,6 +4740,14 @@
4634:: proofs to fewer than 1,024 cells; the projection planner has a separate
4740:: proofs to fewer than 1,024 cells; the projection planner has a separate
4635:: 4,096-step bound. These are inference limits, not language limits.
4741:: 4,096-step bound. These are inference limits, not language limits.
4636::
4742::
4743+:: `unface` is reserved with proj (+reserved-name) and is also handled by
4744+:: type: (unface e) has e's type with every face removed, through cells,
4745+:: gates and collection arguments, keeping unions and recursive molds
4746+:: whole (+itype-unface). It is not a value, it takes one argument, and
4747+:: a bare type variable is unsupported, as field access on one is. A ++
4748+:: whose body is (unface |= …) is a gate for recursion (+unfaced-gate).
4749+:: It lowers to its argument; no lowering is implemented yet.
4750+::
4637:: Supported API imports derive request-gate types atomically for multiple
4751:: Supported API imports derive request-gate types atomically for multiple
4638:: paths, including one typed segment or one diff fold per case. Their checked
4752:: paths, including one typed segment or one diff fold per case. Their checked
4639:: ordinary definitions, mark molds and supported poke constructor are also
4753:: ordinary definitions, mark molds and supported poke constructor are also
@@ -4845,7 +4959,8 @@
4845:: +itype-unify: consistent substitutions, or ~ for a mismatch
4959:: +itype-unify: consistent substitutions, or ~ for a mismatch
4846::
4960::
4847:: Different concrete auras conflict. A variable may become an atom or
4961:: Different concrete auras conflict. A variable may become an atom or
4848−:: a function, but cannot contain itself. Aura-only variables and faces
4962+:: a function, but cannot contain itself. A decimal's variable binds
4963+:: only @ud or @u (+decimal-aura). Aura-only variables and faces
4849:: require further distinctions before this supports general Jibb.
4964:: require further distinctions before this supports general Jibb.
4850::
4965::
4851++ itype-unify
4966++ itype-unify
@@ -4894,10 +5009,10 @@
4894 ?: &(?=(%rnvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
5009 ?: &(?=(%rnvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
4895 ?: &(?=(%avar -.a) ?=(%rnvar -.b)) `[[id.a b] sub]
5010 ?: &(?=(%avar -.a) ?=(%rnvar -.b)) `[[id.a b] sub]
4896 ?: ?=(%rnvar -.a)
5011 ?: ?=(%rnvar -.a)
4897− ?. |(?=(%rnvar -.b) ?=(%atom -.b)) ~
5012+ ?. |(?=(%rnvar -.b) &(?=(%atom -.b) (decimal-aura aura.b))) ~
4898 `[[id.a b] sub]
5013 `[[id.a b] sub]
4899 ?: ?=(%rnvar -.b)
5014 ?: ?=(%rnvar -.b)
4900− ?. ?=(%atom -.a) ~
5015+ ?. &(?=(%atom -.a) (decimal-aura aura.a)) ~
4901 `[[id.b a] sub]
5016 `[[id.b a] sub]
4902 ?: &(?=(%avar -.a) ?=(%rvar -.b)) `[[id.a b] sub]
5017 ?: &(?=(%avar -.a) ?=(%rvar -.b)) `[[id.a b] sub]
4903 ?: &(?=(%rvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
5018 ?: &(?=(%rvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
@@ -4908,14 +5023,15 @@
4908 ?. ?=(%atom -.a) ~
5023 ?. ?=(%atom -.a) ~
4909 `[[id.b a] sub]
5024 `[[id.b a] sub]
4910 :: The narrower decimal constraint survives a match with an atom
5025 :: The narrower decimal constraint survives a match with an atom
4911− :: variable; decimal syntax alone does not make it a loobean.
5026+ :: variable; decimal syntax alone does not make it a loobean. A
5027+ :: concrete aura takes a decimal only if it is @ud or @u.
4912 ?: &(?=(%nvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
5028 ?: &(?=(%nvar -.a) ?=(%avar -.b)) `[[id.b a] sub]
4913 ?: &(?=(%avar -.a) ?=(%nvar -.b)) `[[id.a b] sub]
5029 ?: &(?=(%avar -.a) ?=(%nvar -.b)) `[[id.a b] sub]
4914 ?: ?=(%nvar -.a)
5030 ?: ?=(%nvar -.a)
4915− ?. |(?=(%nvar -.b) ?=(%atom -.b)) ~
5031+ ?. |(?=(%nvar -.b) &(?=(%atom -.b) (decimal-aura aura.b))) ~
4916 `[[id.a b] sub]
5032 `[[id.a b] sub]
4917 ?: ?=(%nvar -.b)
5033 ?: ?=(%nvar -.b)
4918− ?. ?=(%atom -.a) ~
5034+ ?. &(?=(%atom -.a) (decimal-aura aura.a)) ~
4919 `[[id.b a] sub]
5035 `[[id.b a] sub]
4920 ?: ?=(%avar -.a)
5036 ?: ?=(%avar -.a)
4921 ?. |(?=(%avar -.b) ?=(%atom -.b) ?=(%any-atom -.b) ?=(%flag -.b)) ~
5037 ?. |(?=(%avar -.b) ?=(%atom -.b) ?=(%any-atom -.b) ?=(%flag -.b)) ~
@@ -4939,6 +5055,35 @@
4939 $(a tal.a, b tal.b, sub u.first)
5055 $(a tal.a, b tal.b, sub u.first)
4940 ~
5056 ~
4941::
5057::
5058+:: +itype-unface: t with every face removed, for (unface e)
5059+::
5060+:: It strips through cells, through a gate's sample and product and
5061+:: through a built-in collection's arguments, the prelude's unit
5062+:: included, walking bound variables. Other unions and recursive
5063+:: molds are compared by name or by their exact cases, so stripping
5064+:: inside them would stop them from fitting their own name: they are
5065+:: kept whole. An unbound variable stays, so faces it is bound to
5066+:: later are kept. The unit keeps its own u=, as a list keeps i= and
5067+:: t= in its mold.
5068+::
5069+++ itype-unface
5070+ |= [t=itype sub=isub]
5071+ ^- itype
5072+ =. t (itype-walk t sub)
5073+ ?+ -.t t
5074+ %face $(t body.t)
5075+ %cell [%cell $(t hed.t) $(t tal.t)]
5076+ %fn [%fn $(t sample.t) $(t product.t)]
5077+ %collection [%collection name.t (turn args.t |=(a=itype ^$(t a)))]
5078+ %union
5079+ ?. =(origin.t `[/lib/jibb/prelude/jibb %unit]) t
5080+ ?. ?=([* ~] args.t) t
5081+ =/ nil=itype [%const [%null %n 0 '~']]
5082+ ?. =(cases.t ~[nil [%cell nil [%face %u i.args.t]]]) t
5083+ =/ arg=itype $(t i.args.t)
5084+ t(cases ~[nil [%cell nil [%face %u arg]]], args ~[arg])
5085+ ==
5086+::
4942+$ igf-form [typ=itype sub=isub left=@ud]
5087+$ igf-form [typ=itype sub=isub left=@ud]
4943+$ igf-forms [types=(list itype) sub=isub left=@ud]
5088+$ igf-forms [types=(list itype) sub=isub left=@ud]
4944++ itype-gate-free-forms
5089++ itype-gate-free-forms
@@ -5060,6 +5205,16 @@
5060 ?. =(i.a i.b) |
5205 ?. =(i.a i.b) |
5061 $(a t.a, b t.b)
5206 $(a t.a, b t.b)
5062::
5207::
5208+:: +decimal-aura: whether a bare decimal fits an atom of this aura
5209+::
5210+:: A decimal is a @ud, so as in Hoon it fits @ud and its ancestors
5211+:: @u and @; every other aura takes its own literal (S4).
5212+::
5213+++ decimal-aura
5214+ |= aura=@ta
5215+ ^- ?
5216+ (aura-prefix aura %ud)
5217+::
5063:: Related auras in a structural unification need a common-type rule;
5218:: Related auras in a structural unification need a common-type rule;
5064:: until that rule is implemented, report an unknown rather than error.
5219:: until that rule is implemented, report an unknown rather than error.
5065::
5220::
@@ -5131,10 +5286,84 @@
5131 ?: (aura-prefix aura.a aura.b) `a
5286 ?: (aura-prefix aura.a aura.b) `a
5132 ?: (aura-prefix aura.b aura.a) `b
5287 ?: (aura-prefix aura.b aura.a) `b
5133 ~
5288 ~
5134− ?: &(?=(%any-atom -.a) |(?=(%atom -.b) ?=(%flag -.b))) `a
5289+ ?: &(?=(%any-atom -.a) |(?=(%atom -.b) ?=(%flag -.b) ?=(%const -.b) ?=(%avar -.b) ?=(%rvar -.b) ?=(%nvar -.b) ?=(%rnvar -.b))) `a
5135− ?: &(?=(%any-atom -.b) |(?=(%atom -.a) ?=(%flag -.a))) `b
5290+ ?: &(?=(%any-atom -.b) |(?=(%atom -.a) ?=(%flag -.a) ?=(%const -.a) ?=(%avar -.a) ?=(%rvar -.a) ?=(%nvar -.a) ?=(%rnvar -.a))) `b
5136 ~
5291 ~
5137::
5292::
5293+++ itype-branch-join
5294+ |= [a=itype b=itype sub=isub]
5295+ ^- (unit [typ=itype sub=isub])
5296+ =/ unified=(unit isub) (itype-unify a b sub)
5297+ ?^ unified `[(itype-normalize a u.unified) u.unified]
5298+ =/ common=(unit itype) (itype-concrete-join a b sub)
5299+ ?~ common ~
5300+ `[u.common sub]
5301+::
5302+++ itype-branch-join-with
5303+ |= [candidate=itype types=(list itype) sub=isub]
5304+ ^- (unit [typ=itype sub=isub])
5305+ ?~ types `[(itype-normalize candidate sub) sub]
5306+ =/ joined=(unit [typ=itype sub=isub]) (itype-branch-join candidate i.types sub)
5307+ ?~ joined ~
5308+ $(candidate typ.u.joined, types t.types, sub sub.u.joined)
5309+::
5310+++ itype-branch-unify-list
5311+ |= [types=(list itype) sub=isub]
5312+ ^- (unit [typ=itype sub=isub])
5313+ ?~ types ~
5314+ =/ candidate=itype i.types
5315+ =/ rest=(list itype) t.types
5316+ |-
5317+ ?~ rest `[(itype-normalize candidate sub) sub]
5318+ =/ unified=(unit isub) (itype-unify candidate i.rest sub)
5319+ ?~ unified ~
5320+ $(candidate (itype-normalize candidate u.unified), rest t.rest, sub u.unified)
5321+::
5322+++ itype-branch-any-atom
5323+ |= [types=(list itype) sub=isub]
5324+ ^- (unit itype)
5325+ ?~ types ~
5326+ =/ typ=itype (itype-walk i.types sub)
5327+ ?: ?=(%any-atom -.typ) `typ
5328+ $(types t.types)
5329+::
5330+++ itype-branch-atom-parent
5331+ |= [candidate=itype types=(list itype) sub=isub]
5332+ ^- (unit itype)
5333+ ?~ types `candidate
5334+ =/ typ=itype (itype-walk i.types sub)
5335+ ?. ?=(%atom -.typ) $(types t.types)
5336+ =/ joined=(unit itype) (itype-concrete-join candidate typ sub)
5337+ ?~ joined ~
5338+ $(candidate u.joined, types t.types)
5339+::
5340+++ itype-branch-atom-candidates
5341+ |= [candidates=(list itype) types=(list itype) sub=isub]
5342+ ^- (unit itype)
5343+ ?~ candidates ~
5344+ =/ candidate=itype (itype-walk i.candidates sub)
5345+ ?. ?=(%atom -.candidate) $(candidates t.candidates)
5346+ =/ parent=(unit itype) (itype-branch-atom-parent candidate types sub)
5347+ ?^ parent parent
5348+ $(candidates t.candidates)
5349+::
5350+++ itype-branch-parent
5351+ |= [types=(list itype) sub=isub]
5352+ ^- (unit itype)
5353+ =/ unrestricted=(unit itype) (itype-branch-any-atom types sub)
5354+ ?^ unrestricted unrestricted
5355+ (itype-branch-atom-candidates types types sub)
5356+::
5357+++ itype-branch-join-list
5358+ |= [types=(list itype) sub=isub]
5359+ ^- (unit [typ=itype sub=isub])
5360+ ?~ types ~
5361+ =/ unified=(unit [typ=itype sub=isub]) (itype-branch-unify-list types sub)
5362+ ?^ unified unified
5363+ =/ parent=(unit itype) (itype-branch-parent types sub)
5364+ ?~ parent ~
5365+ (itype-branch-join-with u.parent types sub)
5366+::
5138:: Unifying an already-bound tuple with a faced position would need to
5367:: Unifying an already-bound tuple with a faced position would need to
5139:: update the bound type. Until substitutions can retain that information,
5368:: update the bound type. Until substitutions can retain that information,
5140:: variable-dependent face merges stay unresolved.
5369:: variable-dependent face merges stay unresolved.
@@ -5721,6 +5950,24 @@
5721 ["canonicalization should retain gate-free variables" problems]
5950 ["canonicalization should retain gate-free variables" problems]
5722 =? problems !=((show-atom-constraint canonical-free) " where A contains no gates")
5951 =? problems !=((show-atom-constraint canonical-free) " where A contains no gates")
5723 ["the printer should show gate-free constraints" problems]
5952 ["the printer should show gate-free constraints" problems]
5953+ =/ decimal=itype [%nvar 50]
5954+ =? problems ?=(~ (itype-unify decimal num ~))
5955+ ["a decimal should unify with @ud" problems]
5956+ =? problems ?=(~ (itype-unify [%atom %u] decimal ~))
5957+ ["a decimal should unify with @u" problems]
5958+ =? problems ?=(^ (itype-unify decimal [%atom %dr] ~))
5959+ ["a decimal should not unify with @dr" problems]
5960+ =? problems ?=(^ (itype-unify [%atom %ux] decimal ~))
5961+ ["a decimal should not unify with @ux" problems]
5962+ =/ restricted=(unit isub) (itype-unify decimal [%rvar 51] ~)
5963+ =? problems |(?=(~ restricted) ?=(^ (itype-unify [%rvar 51] [%atom %p] u.restricted)))
5964+ ["arithmetic should keep a decimal's aura rule" problems]
5965+ =/ decimal-any=ifit (itype-fit decimal [%any-atom ~] ~ 52)
5966+ =? problems !?=(%ok -.decimal-any)
5967+ ["a decimal should fit @" problems]
5968+ =/ decimal-noun=ifit (itype-fit decimal [%noun ~] ~ 52)
5969+ =? problems !?=(%ok -.decimal-noun)
5970+ ["a decimal should fit a noun" problems]
5724 problems
5971 problems
5725::
5972::
5726:: The expression inference below is deliberately a fragment: bindings,
5973:: The expression inference below is deliberately a fragment: bindings,
@@ -6099,9 +6346,13 @@
6099 ?~ work ~
6346 ?~ work ~
6100 ?: (hole-known [%var id.i.work] state) $(work t.work)
6347 ?: (hole-known [%var id.i.work] state) $(work t.work)
6101 ?: (hole-uncertain [%var id.i.work] state)
6348 ?: (hole-uncertain [%var id.i.work] state)
6102− `["type hole needs unsupported inference" ~[[at.i.work "type hole"]]]
6349+ `[uncertain-hole-msg ~[[at.i.work "type hole"]]]
6103 `["type hole needs a determined type" ~[[at.i.work "unresolved type hole"]]]
6350 `["type hole needs a determined type" ~[[at.i.work "unresolved type hole"]]]
6104::
6351::
6352+:: +uncertain-hole-msg: unsupported, though it names the hole's site
6353+::
6354+++ uncertain-hole-msg "type hole needs unsupported inference"
6355+::
6105++ itype-vars
6356++ itype-vars
6106 |= t=itype
6357 |= t=itype
6107 ^- (list @ud)
6358 ^- (list @ud)
@@ -6264,15 +6515,67 @@
6264 ^- ?
6515 ^- ?
6265 (itype-var-is-gate-free-fuel n t 256)
6516 (itype-var-is-gate-free-fuel n t 256)
6266::
6517::
6518+:: +named-var: the ID of the nth type variable, written as name
6519+::
6520+:: An ID counts in its low 64 bits. The name a variable was written
6521+:: with, as Msg, sits above them, or 0 for none, so the name travels
6522+:: with the variable through substitution, generalization and
6523+:: instantiation, and the printer can show it (+show-var). No two
6524+:: IDs share a count, so a name never makes two variables one.
6525+::
6526+++ named-var
6527+ |= [name=@t n=@ud]
6528+ ^- @ud
6529+ (add (lsh 6 name) (end 6 n))
6530+::
6531+:: +var-name: the name in a type variable's ID, or 0 for none
6532+::
6533+++ var-name
6534+ |= id=@ud
6535+ ^- @t
6536+ (rsh 6 id)
6537+::
6538+:: +var-count: a type variable's ID without its name
6539+::
6540+++ var-count
6541+ |= id=@ud
6542+ ^- @ud
6543+ (end 6 id)
6544+::
6545+:: +canonical-itype: t with the variables in vars renumbered to print
6546+::
6547+:: A variable keeps its name unless one before it in vars has the same
6548+:: name. The others take numbers from 0, skipping any whose letter
6549+:: (+show-var) is a name in vars, so a printed type never shows one
6550+:: name for two variables.
6551+::
6267++ canonical-itype
6552++ canonical-itype
6268 |= [t=itype vars=(list @ud)]
6553 |= [t=itype vars=(list @ud)]
6269 ^- itype
6554 ^- itype
6555+ =/ names=(list @t) (turn vars var-name)
6556+ =/ used=(list @t) ~
6270 =/ ren=isub ~
6557 =/ ren=isub ~
6271 =/ n=@ud 0
6558 =/ n=@ud 0
6272 |-
6559 |-
6273 ?~ vars (itype-rename t ren)
6560 ?~ vars (itype-rename t ren)
6561+ =/ name=@t (var-name i.vars)
6562+ =/ own=? &(!=(0 name) !(lien used |=(u=@t =(u name))))
6563+ =? n !own (letter-free n names)
6564+ =/ id=@ud ?:(own (named-var name 0) n)
6274− =/ 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])))
6565+ =/ 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])))
6275− $(vars t.vars, ren [[i.vars replacement] ren], n +(n))
6566+ $(vars t.vars, ren [[i.vars replacement] ren], n ?:(own n +(n)), used ?:(own [name used] used))
6567+::
6568+:: +letter-free: the first number from n whose letter is none of names
6569+::
6570+++ letter-free
6571+ |= [n=@ud names=(list @t)]
6572+ ^- @ud
6573+ ?. (lien names |=(m=@t =(m (crip (show-var n))))) n
6574+ $(n +(n))
6575+::
6576+:: +instantiate-scheme: a scheme's type with fresh quantified variables
6577+::
6578+:: Each fresh variable keeps the name of the one it replaces.
6276::
6579::
6277++ instantiate-scheme
6580++ instantiate-scheme
6278 |= [scheme=ischeme state=istate]
6581 |= [scheme=ischeme state=istate]
@@ -6281,12 +6584,13 @@
6281 =/ vars=(list @ud) vars.scheme
6584 =/ vars=(list @ud) vars.scheme
6282 |-
6585 |-
6283 ?~ vars [(itype-rename typ.scheme ren) state]
6586 ?~ vars [(itype-rename typ.scheme ren) state]
6587+ =/ fresh=@ud (named-var (var-name i.vars) next.state)
6284 =/ replacement=itype
6588 =/ replacement=itype
6285− ?:((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])))
6589+ ?:((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])))
6286 :: A generalized atom variable is a valid origin for re-generalizing
6590 :: A generalized atom variable is a valid origin for re-generalizing
6287 :: an alias, just as a sample binder is.
6591 :: an alias, just as a sample binder is.
6288 =/ st=istate state(next +(next.state))
6592 =/ st=istate state(next +(next.state))
6289− =? binders.st |(?=(%fvar -.replacement) ?=(%avar -.replacement) ?=(%rvar -.replacement)) [next.state binders.state]
6593+ =? binders.st |(?=(%fvar -.replacement) ?=(%avar -.replacement) ?=(%rvar -.replacement)) [fresh binders.state]
6290 $(vars t.vars, ren [[i.vars replacement] ren], state st)
6594 $(vars t.vars, ren [[i.vars replacement] ren], state st)
6291::
6595::
6292++ icap-lookup
6596++ icap-lookup
@@ -7146,7 +7450,8 @@
7146 ?: in-mold.state ~
7450 ?: in-mold.state ~
7147 =/ n=(unit @ud) (icap-lookup name.sh caps.state)
7451 =/ n=(unit @ud) (icap-lookup name.sh caps.state)
7148 ?^ n `[[%var u.n] state]
7452 ?^ n `[[%var u.n] state]
7453+ =/ id=@ud (named-var name.sh next.state)
7149− `[[%var next.state] state(next +(next.state), caps [[name.sh next.state at.sh] caps.state])]
7454+ `[[%var id] state(next +(next.state), caps [[name.sh id at.sh] caps.state])]
7150 * ~
7455 * ~
7151 ==
7456 ==
7152::
7457::
@@ -7179,12 +7484,12 @@
7179 ^- isample-result
7484 ^- isample-result
7180 ?- -.s
7485 ?- -.s
7181 %bind
7486 %bind
7182− ?: |(=(name.s %proj) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
7487+ ?: |((reserved-name name.s) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
7183 [%| "sample shadows a name"]
7488 [%| "sample shadows a name"]
7184 =/ t=itype [%var next.state]
7489 =/ t=itype [%var next.state]
7185 [%& t [[name.s [t ~]] env] state(next +(next.state), binders [next.state binders.state])]
7490 [%& t [[name.s [t ~]] env] state(next +(next.state), binders [next.state binders.state])]
7186 %face
7491 %face
7187− ?: |(=(name.s %proj) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
7492+ ?: |((reserved-name name.s) ?=(^ (ienv-lookup name.s env)) (lien globals.state |=(x=term =(x name.s))))
7188 [%| "sample shadows a name"]
7493 [%| "sample shadows a name"]
7189 =/ t=(unit [typ=itype state=istate]) (infer-simple-shape shape.s state)
7494 =/ t=(unit [typ=itype state=istate]) (infer-simple-shape shape.s state)
7190 ?~ t [%| "sample mold is not supported by partial inference"]
7495 ?~ t [%| "sample mold is not supported by partial inference"]
@@ -7252,7 +7557,7 @@
7252 |-
7557 |-
7253 ?~ ds &
7558 ?~ ds &
7254 ?: ?=(%mold -.i.ds) $(ds t.ds)
7559 ?: ?=(%mold -.i.ds) $(ds t.ds)
7255− ?: =(name.i.ds %proj) |
7560+ ?: (reserved-name name.i.ds) |
7256 ?. (unique-value-name name.i.ds names) |
7561 ?. (unique-value-name name.i.ds names) |
7257 ?: ?=(^ (ienv-lookup name.i.ds env)) |
7562 ?: ?=(^ (ienv-lookup name.i.ds env)) |
7258 ?: (lien globals.state |=(n=term =(n name.i.ds))) |
7563 ?: (lien globals.state |=(n=term =(n name.i.ds))) |
@@ -7276,7 +7581,7 @@
7276 |-
7581 |-
7277 ?~ locals &
7582 ?~ locals &
7278 =/ n=term name.i.locals
7583 =/ n=term name.i.locals
7279− ?: =(n %proj) |
7584+ ?: (reserved-name n) |
7280 ?. (unique-value-name n names) |
7585 ?. (unique-value-name n names) |
7281 ?: (lien molds.state |=(m=[name=term body=shape] =(n name.m))) |
7586 ?: (lien molds.state |=(m=[name=term body=shape] =(n name.m))) |
7282 ?: (lien marks.state |=(m=term =(n m))) |
7587 ?: (lien marks.state |=(m=term =(n m))) |
@@ -7426,17 +7731,123 @@
7426 ^- istate
7731 ^- istate
7427 ?~ sites state
7732 ?~ sites state
7428 ?: ?=(^ (icap-lookup name.i.sites caps.state)) $(sites t.sites)
7733 ?: ?=(^ (icap-lookup name.i.sites caps.state)) $(sites t.sites)
7734+ =/ id=@ud (named-var name.i.sites next.state)
7429− $(sites t.sites, state state(next +(next.state), caps [[name.i.sites next.state at.i.sites] caps.state]))
7735+ $(sites t.sites, state state(next +(next.state), caps [[name.i.sites id at.i.sites] caps.state]))
7430::
7736::
7431++ reserve-def-caps
7737++ reserve-def-caps
7432 |= [e=expr state=istate]
7738 |= [e=expr state=istate]
7433 ^- istate
7739 ^- istate
7434 (reserve-cap-sites (scope-expr e) state)
7740 (reserve-cap-sites (scope-expr e) state)
7435::
7741::
7742+:: +definite-diag: whether a failure is an error in the program itself
7743+::
7744+:: A definite error names the sites that conflict. A form partial
7745+:: inference does not support names none, and neither does a name
7746+:: that is not inferred yet, such as a sibling that waits for a later
7747+:: pass. An uncertain hole is the one unsupported result with a site.
7748+::
7749+++ definite-diag
7750+ |= diag=idiag
7751+ ^- ?
7752+ ?~ sites.diag |
7753+ !=(msg.diag uncertain-hole-msg)
7754+::
7755+:: +shared-types: what a body's shared variables resolve to
7756+::
7757+:: The variables free in env or in the enclosing capitals, such as an
7758+:: enclosing gate's untyped sample, are shared by all of the body's
7759+:: locals. A local keeps monomorphic only the variables that these
7760+:: resolve to; it generalizes the rest, which each use renames.
7761+::
7762+++ shared-types
7763+ |= [env=ienv caps=icaps sub=isub]
7764+ ^- (list [id=@ud typ=itype])
7765+ %+ turn
7766+ (unique-type-vars (weld (free-env-vars env sub) (free-cap-vars caps sub)))
7767+ |=(id=@ud [id (itype-normalize [%var id] sub)])
7768+::
7769+:: +shared-moved: whether a sibling bound or refined a shared variable
7770+::
7771+:: A sibling that infers can constrain a shared variable and so turn
7772+:: another local's failure into a success: +itype-fit accepts any type
7773+:: it can prove empty, so after `^- !! x` every cast of x fits. Such a
7774+:: failure can depend on the order siblings are tried in. A variable
7775+:: that a sibling keeps monomorphic occurs in what a shared variable
7776+:: resolves to, so constraining it moves a shared variable too. A
7777+:: substitution only grows, so when none moved, every sibling inferred
7778+:: so far, and the local, ran against the entry state and generalized
7779+:: schemes alone.
7780+::
7781+++ shared-moved
7782+ |= [shared=(list [id=@ud typ=itype]) sub=isub]
7783+ ^- ?
7784+ (lien shared |=([id=@ud typ=itype] !=(typ (itype-normalize [%var id] sub))))
7785+::
7786+:: +closed-local: whether a local cannot see any shared variable
7787+::
7788+:: A local that names no sibling, itself included, no name whose type
7789+:: had a free variable when the body was entered, and no enclosing
7790+:: capital that did, is inferred from generalized schemes and known
7791+:: types alone. What its siblings do cannot change its result, so its
7792+:: error is its own in any order. +sub is the substitution on entry,
7793+:: since a sibling may since have bound such a variable. The names are
7794+:: syntactic and ignore binders, so this errs closed.
7795+::
7796+++ closed-local
7797+ |= [d=def siblings=(list term) env=ienv caps=icaps sub=isub]
7798+ ^- ?
7799+ ?. ?=(%value -.d) |
7800+ =/ deps=(list term) (dependency-expr val.d)
7801+ ?: (lien deps |=(n=term |(=(n name.d) (lien siblings |=(s=term =(s n)))))) |
7802+ ?: %+ lien deps
7803+ |= n=term
7804+ =/ sc=(unit ischeme) (ienv-lookup n env)
7805+ ?~ sc |
7806+ ?=(^ (free-env-vars ~[[n u.sc]] sub))
7807+ |
7808+ %+ levy (scope-expr val.d)
7809+ |= site=icap-site
7810+ =/ id=(unit @ud) (icap-lookup name.site caps)
7811+ ?~ id &
7812+ ?=(~ (itype-vars (itype-normalize [%var u.id] sub)))
7813+::
7814+:: +infer-local-defs: infer a body's local values in dependency order
7815+::
7816+:: A definition that fails, or whose type is still pending, waits for
7817+:: the next pass, since it may refer to a sibling inferred later. When
7818+:: a pass makes no progress and no cyclic group applies, report the
7819+:: definite error of the earliest waiting definition, if no order of
7820+:: the siblings could change it; otherwise the message stays generic.
7821+::
7822+:: A failure counts only if it names its sites. The failure of a
7823+:: local that sees no shared variable (+closed-local) is its own. Any
7824+:: other failure counts only if no shared variable had moved when it
7825+:: was tried, and, when the body has shared variables, every other
7826+:: waiting definition also failed with sites: one that waits without
7827+:: them, on a checker limit, a pending tag or its own nested stall,
7828+:: might in another order, or once supported, constrain a shared
7829+:: variable and so let the failing local pass. When all of them failed
7830+:: with sites and none moved a shared variable, the state is the same
7831+:: in every order. With no shared variables, each local is inferred
7832+:: from generalized schemes alone.
7833+::
7834+:: A cyclic group's own errors are not kept. A definition that infers
7835+:: but is then unsupported reports that at once: a failure recorded
7836+:: earlier in the pass may still pass on a retry, once a sibling has
7837+:: constrained a shared variable.
7838+::
7436++ infer-local-defs
7839++ infer-local-defs
7437 |= [ds=(list def) env=ienv state=istate]
7840 |= [ds=(list def) env=ienv state=istate]
7438 ^- ilocal-result
7841 ^- ilocal-result
7842+ =/ shared=(list [id=@ud typ=itype]) (shared-types env caps.state sub.state)
7439 =/ remaining=(list def) ~
7843 =/ remaining=(list def) ~
7844+ =/ siblings=(list term) (global-value-names ds)
7845+ =/ entry=isub sub.state
7846+ :: this pass's failures with sites that are closed or were tried before
7847+ :: any shared variable moved, newest first; and whether a definition
7848+ :: waits without sites
7849+ =/ failures=(list [diag=idiag closed=?]) ~
7850+ =/ blocked=? |
7440 =/ progressed=? |
7851 =/ progressed=? |
7441 |-
7852 |-
7442 ?~ ds
7853 ?~ ds
@@ -7446,16 +7857,35 @@
7446 =/ groups=icomponents (graph-components pending (global-value-names pending))
7857 =/ groups=icomponents (graph-components pending (global-value-names pending))
7447 =/ grouped=(unit [rest=(list def) env=ienv state=istate])
7858 =/ grouped=(unit [rest=(list def) env=ienv state=istate])
7448 (try-local-group pending groups env state)
7859 (try-local-group pending groups env state)
7860+ ?~ grouped
7861+ =/ sure=(list [diag=idiag closed=?])
7862+ ?: |(?=(~ shared) !blocked) failures
7863+ (skim failures |=([diag=idiag closed=?] closed))
7864+ ?^ sure [%| diag:(rear sure)]
7449− ?~ grouped [%| ["local definitions need unsupported inference" ~]]
7865+ [%| ["local definitions need unsupported inference" ~]]
7450− $(ds rest.u.grouped, remaining ~, env env.u.grouped, state state.u.grouped, progressed |)
7866+ $(ds rest.u.grouped, remaining ~, failures ~, blocked |, env env.u.grouped, state state.u.grouped, progressed |)
7451− $(ds (flop remaining), remaining ~, progressed |)
7867+ $(ds (flop remaining), remaining ~, failures ~, blocked |, progressed |)
7452 =/ d=def i.ds
7868 =/ d=def i.ds
7453 ?> ?=(%value -.d)
7869 ?> ?=(%value -.d)
7454 =/ local-state=istate (reserve-def-caps val.d state)
7870 =/ local-state=istate (reserve-def-caps val.d state)
7455− =/ inferred=iresult (infer-fragment val.d env local-state)
7871+ =/ plain=iresult (infer-fragment val.d env local-state)
7456− =/ retried=? ?=(%| -.inferred)
7872+ =/ inferred=iresult
7873+ ?: ?=(%& -.plain) plain
7457− =? inferred retried (infer-recursive-gate d env local-state)
7874+ (infer-recursive-gate d env local-state)
7875+ ?: ?=(%| -.inferred)
7876+ :: For a value that is not a gate the retry only says so; keep the
7877+ :: first failure unless the retry found a definite error.
7878+ =/ failure=idiag
7879+ ?: ?=(%& -.plain) p.inferred
7880+ ?: (definite-diag p.inferred) p.inferred
7881+ p.plain
7882+ ?. (definite-diag failure) $(ds t.ds, remaining [d remaining], blocked &)
7883+ =/ closed=? (closed-local d siblings env caps.state entry)
7884+ =? failures |(closed !(shared-moved shared sub.state))
7885+ [[failure closed] failures]
7458− ?: ?=(%| -.inferred) $(ds t.ds, remaining [d remaining])
7886+ $(ds t.ds, remaining [d remaining])
7887+ :: Only the deferred transaction adds obligations, and it keeps no
7888+ :: failure reason. Obligations from a local are a checker limit.
7459 ?: !=(obligations.state.p.inferred obligations.state) [%| ["deferred local definition needs unsupported inference" ~]]
7889 ?: !=(obligations.state.p.inferred obligations.state) [%| ["deferred local definition needs unsupported inference" ~]]
7460 =. state.p.inferred (promote-restricted-numbers state.p.inferred env)
7890 =. state.p.inferred (promote-restricted-numbers state.p.inferred env)
7461 =. state.p.inferred (default-hole-numbers holes.state.p.inferred holes.state state.p.inferred env !(itype-has-gate (itype-normalize typ.p.inferred sub.state.p.inferred)))
7891 =. state.p.inferred (default-hole-numbers holes.state.p.inferred holes.state state.p.inferred env !(itype-has-gate (itype-normalize typ.p.inferred sub.state.p.inferred)))
@@ -7469,14 +7899,15 @@
7469 [%| ["explicit capital constraints are not supported by partial inference" ~]]
7899 [%| ["explicit capital constraints are not supported by partial inference" ~]]
7470 =/ typ=itype (itype-normalize typ.p.inferred sub.state.p.inferred)
7900 =/ typ=itype (itype-normalize typ.p.inferred sub.state.p.inferred)
7471 ?: |((pending-tags tags.state.p.inferred sub.state.p.inferred) (itype-has-tag typ))
7901 ?: |((pending-tags tags.state.p.inferred sub.state.p.inferred) (itype-has-tag typ))
7472− $(ds t.ds, remaining [d remaining])
7902+ $(ds t.ds, remaining [d remaining], blocked &)
7473 ?: (unsupported-atom-vars typ caps.state.p.inferred binders.state.p.inferred sub.state.p.inferred)
7903 ?: (unsupported-atom-vars typ caps.state.p.inferred binders.state.p.inferred sub.state.p.inferred)
7474− $(ds t.ds, remaining [d remaining])
7904+ $(ds t.ds, remaining [d remaining], blocked &)
7475 =/ free=(list @ud)
7905 =/ free=(list @ud)
7476 (weld (free-env-vars env sub.state.p.inferred) (free-cap-vars caps.state sub.state.p.inferred))
7906 (weld (free-env-vars env sub.state.p.inferred) (free-cap-vars caps.state sub.state.p.inferred))
7477 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
7907 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
7478 =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
7908 =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
7909+ =/ named=[typ=itype vars=(list @ud)] (cap-names typ vars caps.state.p.inferred sub.state.p.inferred)
7479− $(ds t.ds, env [[name.d [typ vars]] env], state state.p.inferred(caps caps.state, holes holes.state), progressed &)
7910+ $(ds t.ds, env [[name.d named] env], state state.p.inferred(caps caps.state, holes holes.state), progressed &)
7480::
7911::
7481:: Try complete cyclic local groups after individual definitions stall.
7912:: Try complete cyclic local groups after individual definitions stall.
7482:: Components with non-gates or unresolved constraints stay unavailable.
7913:: Components with non-gates or unresolved constraints stay unavailable.
@@ -7566,6 +7997,8 @@
7566 ?: &(?=(%collection -.expected) =(%list name.expected) (context-list-expression e))
7997 ?: &(?=(%collection -.expected) =(%list name.expected) (context-list-expression e))
7567 (infer-list-context e expected env state context)
7998 (infer-list-context e expected env state context)
7568 ?: ?=(%branch -.e)
7999 ?: ?=(%branch -.e)
8000+ =/ named=(unit idiag) (branch-tag-name e env state)
8001+ ?^ named [%| u.named]
7569 =/ empty-list=(unit iresult) (empty-list-null-branch e env state `[expected context])
8002 =/ empty-list=(unit iresult) (empty-list-null-branch e env state `[expected context])
7570 ?^ empty-list u.empty-list
8003 ?^ empty-list u.empty-list
7571 ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
8004 ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
@@ -7606,6 +8039,8 @@
7606 ?^ missing [%| u.missing]
8039 ?^ missing [%| u.missing]
7607 =/ nested=(unit idiag) (nested-missing-tag e typ.p.value expected sub.state.p.value next.state.p.value context)
8040 =/ nested=(unit idiag) (nested-missing-tag e typ.p.value expected sub.state.p.value next.state.p.value context)
7608 ?^ nested [%| u.nested]
8041 ?^ nested [%| u.nested]
8042+ =/ decimal=(unit idiag) (decimal-misfit e typ.p.value expected sub.state.p.value next.state.p.value)
8043+ ?^ decimal [%| u.decimal]
7609 ?: &(?=(%collection -.expected) =(%list name.expected))
8044 ?: &(?=(%collection -.expected) =(%list name.expected))
7610 [%| ["branch arm does not fit its expected list" ~[[context "expected list"] [(span-of e) "branch arm"]]]]
8045 [%| ["branch arm does not fit its expected list" ~[[context "expected list"] [(span-of e) "branch arm"]]]]
7611 ?: ?=(%flag -.expected)
8046 ?: ?=(%flag -.expected)
@@ -7671,11 +8106,15 @@
7671 =/ fit=ifit (itype-fit typ.p.tail target sub.state.p.tail next.state.p.tail)
8106 =/ fit=ifit (itype-fit typ.p.tail target sub.state.p.tail next.state.p.tail)
7672 ?: ?=(%unknown -.fit) [%| ["list tail constraint is not supported by partial inference" ~]]
8107 ?: ?=(%unknown -.fit) [%| ["list tail constraint is not supported by partial inference" ~]]
7673 ?: ?=(%bad -.fit)
8108 ?: ?=(%bad -.fit)
8109+ =/ decimal=(unit idiag) (decimal-misfit val.i.t.items.e typ.p.tail target sub.state.p.tail next.state.p.tail)
8110+ ?^ decimal [%| u.decimal]
7674 [%| ["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)]]]]
8111 [%| ["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)]]]]
7675 [%& target state.p.tail(sub sub.fit, next next.fit)]
8112 [%& target state.p.tail(sub sub.fit, next next.fit)]
7676::
8113::
8114+:: done holds the items already checked, the last first, so that a
8115+:: decimal among them can be blamed when a later item fixes its aura.
7677++ infer-open-list-items
8116++ infer-open-list-items
7678− |= [items=(list expr) expected=itype env=ienv state=istate context=span]
8117+ |= [items=(list expr) expected=itype env=ienv state=istate context=span done=(list expr)]
7679 ^- iresult
8118 ^- iresult
7680 ?~ items [%& expected state]
8119 ?~ items [%& expected state]
7681 =/ target=itype (itype-walk expected sub.state)
8120 =/ target=itype (itype-walk expected sub.state)
@@ -7691,10 +8130,18 @@
7691 ?: ?=(%bad -.fit)
8130 ?: ?=(%bad -.fit)
7692 ?: |((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))
8131 ?: |((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))
7693 [%| ["list item widening is not supported by partial inference" ~]]
8132 [%| ["list item widening is not supported by partial inference" ~]]
8133+ =/ decimal=(unit idiag) (decimal-misfit i.items typ.p.value target sub.state.p.value next.state.p.value)
8134+ ?^ decimal [%| u.decimal]
8135+ =/ earlier=(list expr) (flop done)
8136+ |- ^- iresult
8137+ ?^ earlier
8138+ =/ found=(unit idiag) (decimal-misfit-at i.earlier typ.p.value sub.state.p.value)
8139+ ?^ found [%| u.found]
8140+ $(earlier t.earlier)
7694 [%| ["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)]]]]
8141 [%| ["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)]]]]
7695 ?: (itype-has-tag (itype-normalize expected sub.fit))
8142 ?: (itype-has-tag (itype-normalize expected sub.fit))
7696 [%| ["list item needs context in partial inference" ~]]
8143 [%| ["list item needs context in partial inference" ~]]
7697− $(items t.items, state state.p.value(sub sub.fit, next next.fit))
8144+ $(items t.items, state state.p.value(sub sub.fit, next next.fit), done [i.items done])
7698::
8145::
7699++ infer-list-items
8146++ infer-list-items
7700 |= [items=(list expr) expected=itype env=ienv state=istate context=span]
8147 |= [items=(list expr) expected=itype env=ienv state=istate context=span]
@@ -7715,6 +8162,8 @@
7715 ?^ missing [%| u.missing]
8162 ?^ missing [%| u.missing]
7716 =/ nested=(unit idiag) (nested-missing-tag i.items typ.p.value target sub.state.p.value next.state.p.value context)
8163 =/ nested=(unit idiag) (nested-missing-tag i.items typ.p.value target sub.state.p.value next.state.p.value context)
7717 ?^ nested [%| u.nested]
8164 ?^ nested [%| u.nested]
8165+ =/ decimal=(unit idiag) (decimal-misfit i.items typ.p.value target sub.state.p.value next.state.p.value)
8166+ ?^ decimal [%| u.decimal]
7718 [%| ["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)]]]]
8167 [%| ["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)]]]]
7719 $(items t.items, state state.p.value(sub sub.fit, next next.fit))
8168 $(items t.items, state state.p.value(sub sub.fit, next next.fit))
7720::
8169::
@@ -7812,7 +8261,7 @@
7812 [%| ["list branch pattern is not supported by partial inference" ~]]
8261 [%| ["list branch pattern is not supported by partial inference" ~]]
7813 =/ binder=(unit [head=term tail=term]) ?:(first-empty second-name first-name)
8262 =/ binder=(unit [head=term tail=term]) ?:(first-empty second-name first-name)
7814 ?~ binder [%| ["list branch pattern is not supported by partial inference" ~]]
8263 ?~ binder [%| ["list branch pattern is not supported by partial inference" ~]]
7815− ?: |(=(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)))))
8264+ ?: |((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)))))
7816 [%| ["pattern binder shadows a name" ~]]
8265 [%| ["pattern binder shadows a name" ~]]
7817 =/ extended=ienv [[head.u.binder [i.args.typ ~]] [tail.u.binder [typ ~]] env]
8266 =/ extended=ienv [[head.u.binder [i.args.typ ~]] [tail.u.binder [typ ~]] env]
7818 =/ left=iresult
8267 =/ left=iresult
@@ -7824,9 +8273,9 @@
7824 (infer-union-context val.y typ.u.expected ?:(first-empty extended env) state.p.left context.u.expected)
8273 (infer-union-context val.y typ.u.expected ?:(first-empty extended env) state.p.left context.u.expected)
7825 ?: ?=(%| -.right) right
8274 ?: ?=(%| -.right) right
7826 ?^ expected [%& typ.u.expected state.p.right]
8275 ?^ expected [%& typ.u.expected state.p.right]
7827− =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
8276+ =/ joined=(unit [typ=itype sub=isub]) (itype-branch-join typ.p.left typ.p.right sub.state.p.right)
7828 ?~ joined [%| ["list branch results need unsupported inference" ~]]
8277 ?~ joined [%| ["list branch results need unsupported inference" ~]]
7829− [%& typ.p.left state.p.right(sub u.joined)]
8278+ [%& typ.u.joined state.p.right(sub sub.u.joined)]
7830::
8279::
7831++ infer-unit-branch
8280++ infer-unit-branch
7832 |= [e=expr env=ienv state=istate expected=(unit [typ=itype context=span])]
8281 |= [e=expr env=ienv state=istate expected=(unit [typ=itype context=span])]
@@ -7849,7 +8298,7 @@
7849 [%| ["unit branch pattern is not supported by partial inference" ~]]
8298 [%| ["unit branch pattern is not supported by partial inference" ~]]
7850 =/ binder=(unit term) ?:(first-empty second-name first-name)
8299 =/ binder=(unit term) ?:(first-empty second-name first-name)
7851 ?~ binder [%| ["unit branch pattern is not supported by partial inference" ~]]
8300 ?~ binder [%| ["unit branch pattern is not supported by partial inference" ~]]
7852− ?: |(=(u.binder %proj) ?=(^ (ienv-lookup u.binder env)) (lien globals.state |=(n=term =(n u.binder))))
8301+ ?: |((reserved-name u.binder) ?=(^ (ienv-lookup u.binder env)) (lien globals.state |=(n=term =(n u.binder))))
7853 [%| ["pattern binder shadows a name" ~]]
8302 [%| ["pattern binder shadows a name" ~]]
7854 =/ payload=(unit itype) (unit-union-payload typ)
8303 =/ payload=(unit itype) (unit-union-payload typ)
7855 ?~ payload [%| ["unit branch subject is not supported by partial inference" ~]]
8304 ?~ payload [%| ["unit branch subject is not supported by partial inference" ~]]
@@ -7868,9 +8317,9 @@
7868 (infer-union-context val.y typ.u.expected ?:(first-empty extended env) state.p.left context.u.expected)
8317 (infer-union-context val.y typ.u.expected ?:(first-empty extended env) state.p.left context.u.expected)
7869 ?: ?=(%| -.right) right
8318 ?: ?=(%| -.right) right
7870 ?^ expected [%& typ.u.expected state.p.right]
8319 ?^ expected [%& typ.u.expected state.p.right]
7871− =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
8320+ =/ joined=(unit [typ=itype sub=isub]) (itype-branch-join typ.p.left typ.p.right sub.state.p.right)
7872 ?~ joined [%| ["unit branch results need unsupported inference" ~]]
8321 ?~ joined [%| ["unit branch results need unsupported inference" ~]]
7873− [%& typ.p.left state.p.right(sub u.joined)]
8322+ [%& typ.u.joined state.p.right(sub sub.u.joined)]
7874::
8323::
7875:: Infer pieces in order, retaining their substitutions and pending tags.
8324:: Infer pieces in order, retaining their substitutions and pending tags.
7876:: A bare decimal literal has no outside type constraint, so it takes its
8325:: A bare decimal literal has no outside type constraint, so it takes its
@@ -7956,11 +8405,83 @@
7956 ^- (unit ienv)
8405 ^- (unit ienv)
7957 =. t ?:(?=(%face -.t) body.t t)
8406 =. t ?:(?=(%face -.t) body.t t)
7958 ?: ?=(%bind -.p)
8407 ?: ?=(%bind -.p)
7959− ?: |(=(name.p %proj) ?=(^ (ienv-lookup name.p env)) (lien globals |=(n=term =(n name.p)))) ~
8408+ ?: |((reserved-name name.p) ?=(^ (ienv-lookup name.p env)) (lien globals |=(n=term =(n name.p)))) ~
7960 `[[name.p [t ~]] env]
8409 `[[name.p [t ~]] env]
7961 ?: ?=(%cell -.p) (union-pattern-bind-items items.p t env globals)
8410 ?: ?=(%cell -.p) (union-pattern-bind-items items.p t env globals)
7962 `env
8411 `env
7963::
8412::
8413+:: +branch-tag-name: a ?- pattern name that spells one of the subject's tags
8414+::
8415+:: A name in a pattern binds, so `stop` written for `%stop` would
8416+:: catch every case left. Where the subject's type at a name's
8417+:: position is a union, or a one-case mold, with a case whose constant
8418+:: there is the term the name spells, the name is an error (Grammar,
8419+:: Patterns). Every path that checks a ?- asks this first, so they
8420+:: agree; it infers the subject apart and drops the state it leaves.
8421+:: A subject that fails, or whose type isn't known yet, is left to the
8422+:: path. Samples aren't patterns: every sample name binds.
8423+++ branch-tag-name
8424+ |= [e=expr env=ienv state=istate]
8425+ ^- (unit idiag)
8426+ ?. ?=(%branch -.e) ~
8427+ ?. (lien arms.e |=(a=arm (union-pattern-has-bind pat.a))) ~
8428+ =/ subject=iresult (infer-fragment subject.e env state)
8429+ ?: ?=(%| -.subject) ~
8430+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8431+ =/ arms=(list arm) arms.e
8432+ |-
8433+ ?~ arms ~
8434+ =/ found=(unit [at=span name=term]) (tag-name-pattern pat.i.arms typ ~)
8435+ ?~ found $(arms t.arms)
8436+ =/ name=tape (trip name.u.found)
8437+ :- ~
8438+ :- "`{name}` binds a name, but the subject's type has `%{name}` here; write %{name}, or * for a catch-all"
8439+ ~[[(span-of subject.e) "subject"] [at.u.found "pattern name"]]
8440+::
8441+:: +tag-name-pattern: the first name in p that t types by a tag
8442+::
8443+:: The walk enters faces, cells and unions, and of a union only the
8444+:: cases a cell pattern can match, so `[t %draft]` reads t at @t. It
8445+:: stops at atoms, `*`, variables, collections and recursive molds,
8446+:: and at a generic union's argument positions, which a type variable
8447+:: types in its mold, as u in `[~ u=A]`.
8448+++ tag-name-pattern
8449+ |= [p=pattern t=itype args=(list itype)]
8450+ ^- (unit [at=span name=term])
8451+ ?. ?=(?(%bind %cell) -.p) ~
8452+ ?: ?=(%face -.t) $(t body.t)
8453+ ?: (lien args |=(a=itype =(a t))) ~
8454+ ?: ?=(%union -.t)
8455+ =/ inner=(list itype) (weld args.t args)
8456+ =/ cases=(list itype) cases.t
8457+ |-
8458+ ?~ cases ~
8459+ ?: &(?=(%cell -.p) =(%none (union-pattern p i.cases))) $(cases t.cases)
8460+ =/ found=(unit [at=span name=term]) (tag-name-pattern p i.cases inner)
8461+ ?^ found found
8462+ $(cases t.cases)
8463+ ?: ?=(%cell -.p) (tag-name-items items.p t args)
8464+ ?. ?=(%const -.t) ~
8465+ ?. &(=(%term form.literal.t) =(%tas aura.literal.t) =(name.p val.literal.t)) ~
8466+ `[at.p name.p]
8467+::
8468+:: +tag-name-items: +tag-name-pattern along a cell pattern's items
8469+::
8470+:: As in +union-pattern-items, the last item takes the rest of the
8471+:: spine. A union mid-spine is read as the rest of the pattern.
8472+++ tag-name-items
8473+ |= [ps=(list pattern) t=itype args=(list itype)]
8474+ ^- (unit [at=span name=term])
8475+ ?~ ps ~
8476+ ?~ t.ps (tag-name-pattern i.ps t args)
8477+ ?: ?=(%face -.t) $(t body.t)
8478+ ?: (lien args |=(a=itype =(a t))) ~
8479+ ?: ?=(%union -.t) (tag-name-pattern [%cell at.i.ps ps] t args)
8480+ ?. ?=(%cell -.t) ~
8481+ =/ head=(unit [at=span name=term]) (tag-name-pattern i.ps hed.t args)
8482+ ?^ head head
8483+ $(ps t.ps, t tal.t)
8484+::
7964:: Split loobean fields into finite refinements for partial patterns.
8485:: Split loobean fields into finite refinements for partial patterns.
7965:: Keep original cases for binder types and preserve whole-case matching
8486:: Keep original cases for binder types and preserve whole-case matching
7966:: before trying refinements. Cap products at 64; unknown, empty or opaque
8487:: before trying refinements. Cap products at 64; unknown, empty or opaque
@@ -8008,6 +8529,8 @@
8008 ^- (unit iresult)
8529 ^- (unit iresult)
8009 ?> ?=(%branch -.e)
8530 ?> ?=(%branch -.e)
8010 ?: ?=(%| -.subject) `subject
8531 ?: ?=(%| -.subject) `subject
8532+ =/ decimal=(unit idiag) (decimal-arms-misfit arms.e typ.p.subject sub.state.p.subject)
8533+ ?^ decimal `[%| u.decimal]
8011 =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8534 =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8012 ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
8535 ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
8013 =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
8536 =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
@@ -8016,13 +8539,14 @@
8016 =/ remaining=(list itype) cases
8539 =/ remaining=(list itype) cases
8017 =/ arms=(list arm) arms.e
8540 =/ arms=(list arm) arms.e
8018 =/ st=istate state.p.subject
8541 =/ st=istate state.p.subject
8019− =/ answer=(unit itype) ~
8542+ =/ results=(list itype) ~
8020 |-
8543 |-
8021 ?~ arms
8544 ?~ arms
8022 ?^ remaining
8545 ?^ remaining
8023 `[%| ["missing union case {(show-itype i.remaining sub.st)}" ~]]
8546 `[%| ["missing union case {(show-itype i.remaining sub.st)}" ~]]
8024− ?~ answer `[%| ["empty union branch is not supported by partial inference" ~]]
8547+ =/ joined=(unit [typ=itype sub=isub]) (itype-branch-join-list (flop results) sub.st)
8025− `[%& u.answer st]
8548+ ?~ joined `[%| ["union branch result matching needs unsupported inference" ~]]
8549+ `[%& typ.u.joined st(sub sub.u.joined)]
8026 =/ a=arm i.arms
8550 =/ a=arm i.arms
8027 ?: (lien remaining |=(c=itype =(%unknown (union-pattern pat.a c))))
8551 ?: (lien remaining |=(c=itype =(%unknown (union-pattern pat.a c))))
8028 ~
8552 ~
@@ -8038,15 +8562,15 @@
8038 =/ body=iresult (infer-fragment val.a u.bound st)
8562 =/ body=iresult (infer-fragment val.a u.bound st)
8039 ?: ?=(%| -.body) `body
8563 ?: ?=(%| -.body) `body
8040 =/ result=itype (itype-normalize typ.p.body sub.state.p.body)
8564 =/ result=itype (itype-normalize typ.p.body sub.state.p.body)
8041− =/ mismatch=? ?~(answer | !=((itype-normalize u.answer sub.state.p.body) result))
8042− ?: mismatch `[%| ["union branch result matching needs unsupported inference" ~]]
8043− $(arms t.arms, remaining (skim remaining |=(c=itype !=(%full (union-pattern pat.a c)))), st state.p.body, answer `result)
8565+ $(arms t.arms, remaining (skim remaining |=(c=itype !=(%full (union-pattern pat.a c)))), st state.p.body, results [result results])
8044::
8566::
8045++ infer-known-union-context-whole
8567++ infer-known-union-context-whole
8046 |= [e=expr expected=itype env=ienv subject=iresult context=span]
8568 |= [e=expr expected=itype env=ienv subject=iresult context=span]
8047 ^- (unit iresult)
8569 ^- (unit iresult)
8048 ?> ?=(%branch -.e)
8570 ?> ?=(%branch -.e)
8049 ?: ?=(%| -.subject) `subject
8571 ?: ?=(%| -.subject) `subject
8572+ =/ decimal=(unit idiag) (decimal-arms-misfit arms.e typ.p.subject sub.state.p.subject)
8573+ ?^ decimal `[%| u.decimal]
8050 =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8574 =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
8051 ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
8575 ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
8052 =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
8576 =/ live=(unit (list itype)) (itype-live-cases cases.typ sub.state.p.subject caps.state.p.subject 4.096)
@@ -8103,14 +8627,16 @@
8103 =/ remaining=(list ifinite) cases
8627 =/ remaining=(list ifinite) cases
8104 =/ arms=(list arm) arms.e
8628 =/ arms=(list arm) arms.e
8105 =/ st=istate state.p.subject
8629 =/ st=istate state.p.subject
8106− =/ answer=(unit itype) ~
8630+ =/ results=(list itype) ~
8107 |-
8631 |-
8108 ?~ arms
8632 ?~ arms
8109 ?^ remaining
8633 ?^ remaining
8110 [%| ["missing union case {(show-itype part.i.remaining sub.st)}" ~]]
8634 [%| ["missing union case {(show-itype part.i.remaining sub.st)}" ~]]
8111− ?~ answer [%| ["empty union branch is not supported by partial inference" ~]]
8635+ ?~ results [%| ["empty union branch is not supported by partial inference" ~]]
8112− ?~ expected [%& u.answer st]
8636+ ?^ expected [%& typ.u.expected st]
8113− [%& typ.u.expected st]
8637+ =/ joined=(unit [typ=itype sub=isub]) (itype-branch-join-list (flop results) sub.st)
8638+ ?~ joined [%| ["union branch result matching needs unsupported inference" ~]]
8639+ [%& typ.u.joined st(sub sub.u.joined)]
8114 =/ a=arm i.arms
8640 =/ a=arm i.arms
8115 ?: (lien remaining |=(c=ifinite =(%unknown (union-pattern pat.a part.c))))
8641 ?: (lien remaining |=(c=ifinite =(%unknown (union-pattern pat.a part.c))))
8116 [%| ["partial union pattern is not supported by partial inference" ~]]
8642 [%| ["partial union pattern is not supported by partial inference" ~]]
@@ -8138,11 +8664,9 @@
8138 [%| ["union branch arm does not fit its expected type" ~[[context.u.expected "expected type"] [(span-of val.a) "branch arm"]]]]
8664 [%| ["union branch arm does not fit its expected type" ~[[context.u.expected "expected type"] [(span-of val.a) "branch arm"]]]]
8139 ?: (itype-has-tag (itype-normalize typ.u.expected sub.fit))
8665 ?: (itype-has-tag (itype-normalize typ.u.expected sub.fit))
8140 [%| ["union branch result needs context in partial inference" ~]]
8666 [%| ["union branch result needs context in partial inference" ~]]
8141− $(arms t.arms, remaining (skim remaining |=(c=ifinite !=(%full (union-pattern pat.a part.c)))), st state.p.body(sub sub.fit, next next.fit), answer `typ.u.expected)
8667+ $(arms t.arms, remaining (skim remaining |=(c=ifinite !=(%full (union-pattern pat.a part.c)))), st state.p.body(sub sub.fit, next next.fit), results [typ.p.body results])
8142 =/ result=itype (itype-normalize typ.p.body sub.state.p.body)
8668 =/ result=itype (itype-normalize typ.p.body sub.state.p.body)
8143− =/ mismatch=? ?~(answer | !=((itype-normalize u.answer sub.state.p.body) result))
8144− ?: mismatch [%| ["union branch result matching needs unsupported inference" ~]]
8145− $(arms t.arms, remaining (skim remaining |=(c=ifinite !=(%full (union-pattern pat.a part.c)))), st state.p.body, answer `result)
8669+ $(arms t.arms, remaining (skim remaining |=(c=ifinite !=(%full (union-pattern pat.a part.c)))), st state.p.body, results [result results])
8146::
8670::
8147:: Prove a one-arm record pattern covers a known, non-union subject.
8671:: Prove a one-arm record pattern covers a known, non-union subject.
8148:: Variable or partial matches stay unsupported; binding uses the same
8672:: Variable or partial matches stay unsupported; binding uses the same
@@ -8407,7 +8931,9 @@
8407 `subject
8931 `subject
8408::
8932::
8409:: Infer changes only against a fully known record spine. Retain the
8933:: Infer changes only against a fully known record spine. Retain the
8410−:: target type; unknown spines and repeated edits remain unsupported.
8934+:: target type; unknown spines and overlapping edits remain unsupported.
8935+:: An edit's wing, as open.cart, reads through record fields only,
8936+:: outermost first, and its value fits the field it names.
8411++ change-spine-known
8937++ change-spine-known
8412 |= [t=itype sub=isub]
8938 |= [t=itype sub=isub]
8413 ^- ?
8939 ^- ?
@@ -8419,26 +8945,87 @@
8419 $(t tal.t)
8945 $(t tal.t)
8420::
8946::
8421++ infer-change-edits
8947++ infer-change-edits
8422− |= [edits=(list edit) target=itype env=ienv state=istate seen=(list term)]
8948+ |= [edits=(list edit) target=itype env=ienv state=istate seen=(list (list term))]
8423 ^- iresult
8949 ^- iresult
8424 ?~ edits [%& target state]
8950 ?~ edits [%& target state]
8425 =/ entry=edit i.edits
8951 =/ entry=edit i.edits
8426− ?: (lien seen |=(name=term =(name name.entry)))
8952+ =/ outer=(list term) (flop names.entry)
8953+ ?: (lien seen |=(prior=(list term) (wing-overlap prior outer)))
8427 [%| ["repeated change fields are not supported by partial inference" ~]]
8954 [%| ["repeated change fields are not supported by partial inference" ~]]
8428 ?. (change-spine-known target sub.state)
8955 ?. (change-spine-known target sub.state)
8429 [%| ["change target needs a known record in partial inference" ~]]
8956 [%| ["change target needs a known record in partial inference" ~]]
8430− =/ found=(list itype) (record-fields-named name.entry target sub.state)
8957+ =/ field=(each itype idiag) (change-wing-field entry target sub.state)
8431− ?~ found
8958+ ?: ?=(%| -.field) [%| p.field]
8432− [%| ["record has no field `{(trip name.entry)}`" ~[[at.entry "unknown field"]]]]
8433− ?^ t.found [%| ["change field is ambiguous in partial inference" ~]]
8434− =/ expected=itype i.found
8959+ =/ expected=itype p.field
8435 =/ value=iresult (infer-call-context-arg val.entry expected env state at.entry)
8960 =/ value=iresult (infer-call-context-arg val.entry expected env state at.entry)
8436 ?: ?=(%| -.value) value
8961 ?: ?=(%| -.value) value
8437 =/ fit=ifit (itype-fit typ.p.value expected sub.state.p.value next.state.p.value)
8962 =/ fit=ifit (itype-fit typ.p.value expected sub.state.p.value next.state.p.value)
8438 ?: ?=(%unknown -.fit) [%| ["change field constraint is not supported by partial inference" ~]]
8963 ?: ?=(%unknown -.fit) [%| ["change field constraint is not supported by partial inference" ~]]
8439 ?: ?=(%bad -.fit)
8964 ?: ?=(%bad -.fit)
8965+ =/ decimal=(unit idiag) (decimal-misfit val.entry typ.p.value expected sub.state.p.value next.state.p.value)
8966+ ?^ decimal [%| u.decimal]
8440 [%| ["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)]]]]
8967 [%| ["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)]]]]
8441− $(edits t.edits, state state.p.value(sub sub.fit, next next.fit), seen [name.entry seen])
8968+ $(edits t.edits, state state.p.value(sub sub.fit, next next.fit), seen [outer seen])
8969+::
8970+:: +change-wing-field: the type of the field an edit's wing names in
8971+:: a known record target, read through record fields, outermost first
8972+::
8973+++ change-wing-field
8974+ |= [entry=edit target=itype sub=isub]
8975+ ^- (each itype idiag)
8976+ =/ outer=(list term) (flop names.entry)
8977+ =/ k=@ud (lent names.entry)
8978+ =/ typ=itype target
8979+ =| through=(unit [name=term at=span])
8980+ |- ^- (each itype idiag)
8981+ ?~ outer [%& typ]
8982+ =/ here=span (edit-name-at entry (dec k))
8983+ ?: &(?=(^ through) !(change-spine-known typ sub))
8984+ ?. (itype-not-record typ sub)
8985+ [%| ["change wing needs a known record in partial inference" ~]]
8986+ =/ label=tape "field `{(trip name.u.through)}`"
8987+ :- %|
8988+ :- "change wing `{(show-names names.entry)}` goes through `{(trip name.u.through)}`, which is not a record"
8989+ ~[[at.u.through (site-type-note label typ sub)]]
8990+ =/ found=(list itype) (record-fields-named i.outer typ sub)
8991+ ?~ found
8992+ [%| ["record has no field `{(trip i.outer)}`" ~[[here "unknown field"]]]]
8993+ ?^ t.found [%| ["change field is ambiguous in partial inference" ~]]
8994+ $(outer t.outer, k (dec k), typ i.found, through `[i.outer here])
8995+::
8996+:: +edit-name-at: where the kth name of an edit's wing is written,
8997+:: counting from 0: its names are joined by dots from the edit's start
8998+::
8999+++ edit-name-at
9000+ |= [e=edit k=@ud]
9001+ ^- span
9002+ =/ col=@ud col.beg.at.e
9003+ =/ ns=(list term) names.e
9004+ |- ^- span
9005+ ?~ ns at.e
9006+ =/ len=@ud (met 3 i.ns)
9007+ ?: =(0 k) [[line.beg.at.e col] [line.beg.at.e (add col len)]]
9008+ $(ns t.ns, k (dec k), col +((add col len)))
9009+::
9010+:: +itype-not-record: whether a type is surely no record: an atom, a
9011+:: loobean, a list or other collection, a gate, a union or a noun
9012+::
9013+++ itype-not-record
9014+ |= [t=itype sub=isub]
9015+ ^- ?
9016+ =. t (itype-walk t sub)
9017+ ?=(?(%atom %any-atom %flag %const %tag %collection %fn %union %noun %empty) -.t)
9018+::
9019+:: +wing-overlap: whether two edits' wings, outermost first, name the
9020+:: same field or one a field inside the other's
9021+::
9022+++ wing-overlap
9023+ |= [a=(list term) b=(list term)]
9024+ ^- ?
9025+ ?~ a &
9026+ ?~ b &
9027+ ?. =(i.a i.b) |
9028+ $(a t.a, b t.b)
8442::
9029::
8443:: Backtick constructs the canonical prelude unit, after checking its
9030:: Backtick constructs the canonical prelude unit, after checking its
8444:: prepared template has the standard null and [~ u=A] cases.
9031:: prepared template has the standard null and [~ u=A] cases.
@@ -8542,6 +9129,183 @@
8542 ?. ?=(%ok -.first) ~
9129 ?. ?=(%ok -.first) ~
8543 $(items t.items, actual tal.actual, expected tal.expected, sub sub.first, next next.first)
9130 $(items t.items, actual tal.actual, expected tal.expected, sub sub.first, next next.first)
8544::
9131::
9132+:: +decimal-misfit: a decimal's error where another aura is expected
9133+::
9134+:: A bare decimal is a @ud and fits only @ud, @u, @ and * (S4). After
9135+:: a value fails to fit, refit it with each decimal's variable widened
9136+:: to any aura (+decimal-relax), so that a gate's shared capital learns
9137+:: its aura from the other arguments, then walk the value's syntax
9138+:: beside the type it should fit. The first decimal whose place is an
9139+:: atom of another aura gets the error; otherwise ~, and the caller's
9140+:: own error stands.
9141+::
9142+++ decimal-misfit
9143+ |= [e=expr actual=itype expected=itype sub=isub next=@ud]
9144+ ^- (unit idiag)
9145+ =/ loose=isub (turn sub |=(b=ibinding b(val (decimal-relax val.b))))
9146+ =/ fit=ifit (itype-fit (decimal-relax actual) (decimal-relax expected) loose next)
9147+ (decimal-misfit-at e (decimal-relax expected) ?:(?=(%ok -.fit) sub.fit loose))
9148+::
9149+:: +decimal-relax: a type with each decimal's variable taking any aura
9150+::
9151+++ decimal-relax
9152+ |= t=itype
9153+ ^- itype
9154+ ?+ -.t t
9155+ %nvar [%avar id.t]
9156+ %rnvar [%rvar id.t]
9157+ %collection t(args (turn args.t |=(c=itype (decimal-relax c))))
9158+ %grec t(args (turn args.t |=(c=itype (decimal-relax c))))
9159+ %union t(cases (turn cases.t |=(c=itype (decimal-relax c))), args (turn args.t |=(c=itype (decimal-relax c))))
9160+ %face t(body $(t body.t))
9161+ %fn [%fn $(t sample.t) $(t product.t)]
9162+ %cell [%cell $(t hed.t) $(t tal.t)]
9163+ ==
9164+::
9165+:: +decimal-misfit-at: walk a value beside the type it should fit
9166+::
9167+:: Through groups, faces, tuples and term-headed pairs, the union case
9168+:: a tuple's head tag picks, units and list literals.
9169+::
9170+++ decimal-misfit-at
9171+ |= [e=expr expected=itype sub=isub]
9172+ ^- (unit idiag)
9173+ =. expected (itype-walk expected sub)
9174+ ?: ?=(%face -.expected) $(expected body.expected)
9175+ ?+ -.e ~
9176+ %lit (decimal-lit-misfit at.e lit.e expected |)
9177+ %group $(e inner.e)
9178+ %pair $(e (pair-as-cell e))
9179+ %tuple (decimal-misfit-items items.e expected sub)
9180+ %unit
9181+ ?. ?=(%collection -.expected) ~
9182+ ?. &(=(%unit name.expected) ?=([* ~] args.expected)) ~
9183+ $(e val.e, expected i.args.expected)
9184+ %list
9185+ ?. ?=(%collection -.expected) ~
9186+ ?. &(=(%list name.expected) ?=([* ~] args.expected)) ~
9187+ =/ items=(list expr) items.e
9188+ |-
9189+ ?~ items ~
9190+ =/ found=(unit idiag) ^$(e i.items, expected i.args.expected)
9191+ ?^ found found
9192+ $(items t.items)
9193+ ==
9194+::
9195+:: +decimal-misfit-items: a tuple's items beside a cell, the last its tail
9196+::
9197+++ decimal-misfit-items
9198+ |= [items=(list item) expected=itype sub=isub]
9199+ ^- (unit idiag)
9200+ ?~ items ~
9201+ ?~ t.items (decimal-misfit-at val.i.items expected sub)
9202+ =. expected (itype-walk expected sub)
9203+ ?: ?=(%face -.expected) $(expected body.expected)
9204+ ?: ?=(%union -.expected)
9205+ =/ head=expr val.i.items
9206+ ?. ?=(%lit -.head) ~
9207+ =/ case=(unit itype) (decimal-case val.lit.head cases.expected sub)
9208+ ?~ case ~
9209+ $(expected u.case)
9210+ ?. ?=(%cell -.expected) ~
9211+ =/ found=(unit idiag) (decimal-misfit-at val.i.items hed.expected sub)
9212+ ?^ found found
9213+ $(items t.items, expected tal.expected)
9214+::
9215+:: +decimal-pattern-misfit: a decimal pattern where another aura is matched
9216+::
9217+:: The subject's type is known, so no refit is needed. A cell pattern
9218+:: picks its union case by its head, as a tuple does.
9219+::
9220+++ decimal-pattern-misfit
9221+ |= [p=pattern expected=itype sub=isub]
9222+ ^- (unit idiag)
9223+ =. expected (itype-walk expected sub)
9224+ ?: ?=(%face -.expected) $(expected body.expected)
9225+ ?: ?=(%lit -.p) (decimal-lit-misfit at.p lit.p expected &)
9226+ ?. ?=(%cell -.p) ~
9227+ (decimal-pattern-items items.p expected sub)
9228+::
9229+:: +decimal-pattern-items: a cell pattern's items, as +decimal-misfit-items
9230+::
9231+++ decimal-pattern-items
9232+ |= [items=(list pattern) expected=itype sub=isub]
9233+ ^- (unit idiag)
9234+ ?~ items ~
9235+ ?~ t.items (decimal-pattern-misfit i.items expected sub)
9236+ =. expected (itype-walk expected sub)
9237+ ?: ?=(%face -.expected) $(expected body.expected)
9238+ ?: ?=(%union -.expected)
9239+ ?. ?=(%lit -.i.items) ~
9240+ =/ case=(unit itype) (decimal-case val.lit.i.items cases.expected sub)
9241+ ?~ case ~
9242+ $(expected u.case)
9243+ ?. ?=(%cell -.expected) ~
9244+ =/ found=(unit idiag) (decimal-pattern-misfit i.items hed.expected sub)
9245+ ?^ found found
9246+ $(items t.items, expected tal.expected)
9247+::
9248+:: +decimal-arms-misfit: the first arm whose pattern has a misplaced decimal
9249+::
9250+++ decimal-arms-misfit
9251+ |= [arms=(list arm) subject=itype sub=isub]
9252+ ^- (unit idiag)
9253+ ?~ arms ~
9254+ =/ found=(unit idiag) (decimal-pattern-misfit pat.i.arms subject sub)
9255+ ?^ found found
9256+ $(arms t.arms)
9257+::
9258+:: +decimal-case: the one union case whose head is the constant value
9259+::
9260+++ decimal-case
9261+ |= [value=@ cases=(list itype) sub=isub]
9262+ ^- (unit itype)
9263+ =/ hits=(list itype)
9264+ %+ skim cases
9265+ |= c=itype
9266+ =. c (itype-walk c sub)
9267+ ?. ?=(%cell -.c) |
9268+ =/ head=itype (itype-walk hed.c sub)
9269+ =? head ?=(%face -.head) (itype-walk body.head sub)
9270+ &(?=(%const -.head) =(value val.literal.head))
9271+ ?. ?=([* ~] hits) ~
9272+ `i.hits
9273+::
9274+:: +decimal-lit-misfit: the error for a decimal at a place of known type
9275+::
9276+++ decimal-lit-misfit
9277+ |= [at=span l=lit expected=itype pattern=?]
9278+ ^- (unit idiag)
9279+ ?. &(=(%number form.l) =(%ud aura.l)) ~
9280+ ?. ?=(%atom -.expected) ~
9281+ ?: (decimal-aura aura.expected) ~
9282+ `[(decimal-misfit-msg l aura.expected pattern) ~[[at "decimal"]]]
9283+::
9284+:: +decimal-misfit-msg: "`30` is a @ud, not a @dr; write ~s30"
9285+::
9286+:: The hint writes the value in the expected aura's own literal where
9287+:: that reads naturally: 30 seconds, the text "30", the ship ~syd; a
9288+:: date gets an example. Patterns take no dates, durations or knots,
9289+:: so in a pattern those auras get no hint.
9290+::
9291+++ decimal-misfit-msg
9292+ |= [l=lit aura=@ta pattern=?]
9293+ ^- tape
9294+ =/ what=tape "`{(trip txt.l)}` is a @ud, not a @{(trip aura)}"
9295+ =/ hint=tape
9296+ ?: &(pattern ?=(?(%da %dr %ta) aura)) ""
9297+ ?+ aura ""
9298+ %da "a date, as ~2026.1.1"
9299+ %dr (trip (scot %dr (mul val.l ~s1)))
9300+ %p (trip (scot %p val.l))
9301+ %t (show-quoted txt.l)
9302+ %ta "~.{(trip txt.l)}"
9303+ %ux (trip (scot %ux val.l))
9304+ %uv (trip (scot %uv val.l))
9305+ ==
9306+ ?~ hint what
9307+ "{what}; write {hint}"
9308+::
8545:: A term-headed pair is the same noun as a two-item cell. Preserve the
9309:: A term-headed pair is the same noun as a two-item cell. Preserve the
8546:: whole pair span for the synthetic head and the value's own span for
9310:: whole pair span for the synthetic head and the value's own span for
8547:: the payload; unresolved term constraints follow ordinary cell inference.
9311:: the payload; unresolved term constraints follow ordinary cell inference.
@@ -8599,7 +9363,7 @@
8599 ?. =(u.standard [[%collection %list ~[[%var 0]]] ~[0]])
9363 ?. =(u.standard [[%collection %list ~[[%var 0]]] ~[0]])
8600 [%| ["list literal needs the standard prelude in partial inference" ~]]
9364 [%| ["list literal needs the standard prelude in partial inference" ~]]
8601 =/ element=itype [%var next.state]
9365 =/ element=itype [%var next.state]
8602− =/ result=iresult (infer-open-list-items items.e element env state(next +(next.state)) at.e)
9366+ =/ result=iresult (infer-open-list-items items.e element env state(next +(next.state)) at.e ~)
8603 ?: ?=(%| -.result) result
9367 ?: ?=(%| -.result) result
8604 [%& [%collection %list ~[element]] state.p.result]
9368 [%& [%collection %list ~[element]] state.p.result]
8605 %str (infer-string-pieces pieces.e env state)
9369 %str (infer-string-pieces pieces.e env state)
@@ -8631,6 +9395,7 @@
8631 [%& typ.instance state.instance]
9395 [%& typ.instance state.instance]
8632 =/ scheme=(unit ischeme) (ienv-lookup i.names.e env)
9396 =/ scheme=(unit ischeme) (ienv-lookup i.names.e env)
8633 ?~ scheme
9397 ?~ scheme
9398+ ?: =(i.names.e %unface) [%| (unface-value at.e)]
8634 ?~ prelude.state [%| ["name is not available to partial inference" ~]]
9399 ?~ prelude.state [%| ["name is not available to partial inference" ~]]
8635 =/ prelude-entry=(unit ischeme) (ienv-lookup i.names.e values.u.prelude.state)
9400 =/ prelude-entry=(unit ischeme) (ienv-lookup i.names.e values.u.prelude.state)
8636 ?~ prelude-entry [%| ["name is not available to partial inference" ~]]
9401 ?~ prelude-entry [%| ["name is not available to partial inference" ~]]
@@ -8638,7 +9403,10 @@
8638 [%& typ.inst state.inst]
9403 [%& typ.inst state.inst]
8639 =/ instance=[typ=itype state=istate] (instantiate-scheme u.scheme state)
9404 =/ instance=[typ=itype state=istate] (instantiate-scheme u.scheme state)
8640 [%& typ.instance state.instance]
9405 [%& typ.instance state.instance]
9406+ %group
9407+ ?: &(?=(%wing -.inner.e) =(names.inner.e ~[%unface]) ?=(~ (ienv-lookup %unface env)))
9408+ [%| ["unface takes one argument, as (unface e)" ~[[at.e "unface call"]]]]
8641− %group $(e inner.e)
9409+ $(e inner.e)
8642 %change
9410 %change
8643 ?~ edits.e [%| ["a change takes at least one field" ~[[at.e "empty change"]]]]
9411 ?~ edits.e [%| ["a change takes at least one field" ~[[at.e "empty change"]]]]
8644 =/ target=iresult $(e [%wing at.e target.e])
9412 =/ target=iresult $(e [%wing at.e target.e])
@@ -8675,6 +9443,8 @@
8675 ?: ?=(%| -.result) result
9443 ?: ?=(%| -.result) result
8676 [%& typ.p.result state.p.result(globals globals.state, molds molds.state)]
9444 [%& typ.p.result state.p.result(globals globals.state, molds molds.state)]
8677 %branch
9445 %branch
9446+ =/ named=(unit idiag) (branch-tag-name e env state)
9447+ ?^ named [%| u.named]
8678 ?^ defer.state (dg-boolean-branch e env state)
9448 ?^ defer.state (dg-boolean-branch e env state)
8679 ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
9449 ?~ arms.e [%| ["branch is not supported by partial inference" ~]]
8680 ?~ t.arms.e
9450 ?~ t.arms.e
@@ -8715,22 +9485,22 @@
8715 ?: ?=(%| -.right) right
9485 ?: ?=(%| -.right) right
8716 =/ ltype=itype (itype-normalize typ.p.left sub.state.p.right)
9486 =/ ltype=itype (itype-normalize typ.p.left sub.state.p.right)
8717 =/ rtype=itype (itype-normalize typ.p.right sub.state.p.right)
9487 =/ rtype=itype (itype-normalize typ.p.right sub.state.p.right)
8718− ?: &(!=(ltype rtype) |(?=(^ (itype-vars ltype)) ?=(^ (itype-vars rtype))) |((itype-has-fixed-atom ltype) (itype-has-fixed-atom rtype)))
8719− [%| ["branch widening is not supported by partial inference" ~]]
8720− =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
9488+ =/ joined=(unit [typ=itype sub=isub]) (itype-branch-join typ.p.left typ.p.right sub.state.p.right)
8721 ?~ joined
9489 ?~ joined
8722 ?: |((itype-has-recursive ltype) (itype-has-recursive rtype))
9490 ?: |((itype-has-recursive ltype) (itype-has-recursive rtype))
8723 [%| ["recursive branch matching is not supported by partial inference" ~]]
9491 [%| ["recursive branch matching is not supported by partial inference" ~]]
8724 ?: |((itype-has-tag ltype) (itype-has-tag rtype) (itype-has-union ltype) (itype-has-union rtype))
9492 ?: |((itype-has-tag ltype) (itype-has-tag rtype) (itype-has-union ltype) (itype-has-union rtype))
8725 [%| ["branch tag or union context is not supported by partial inference" ~]]
9493 [%| ["branch tag or union context is not supported by partial inference" ~]]
8726− =/ common=(unit itype) (itype-concrete-join typ.p.left typ.p.right sub.state.p.right)
8727− ?^ common [%& u.common state.p.right]
8728 ?: |((itype-has-face typ.p.left sub.state.p.right) (itype-has-face typ.p.right sub.state.p.right))
9494 ?: |((itype-has-face typ.p.left sub.state.p.right) (itype-has-face typ.p.right sub.state.p.right))
8729 [%| ["record branch matching is not supported by partial inference" ~]]
9495 [%| ["record branch matching is not supported by partial inference" ~]]
8730 ?: |((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))
9496 ?: |((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))
8731 [%| ["branch widening is not supported by partial inference" ~]]
9497 [%| ["branch widening is not supported by partial inference" ~]]
9498+ =/ decimal-x=(unit idiag) (decimal-misfit val.x typ.p.left typ.p.right sub.state.p.right next.state.p.right)
9499+ ?^ decimal-x [%| u.decimal-x]
9500+ =/ decimal-y=(unit idiag) (decimal-misfit val.y typ.p.right typ.p.left sub.state.p.right next.state.p.right)
9501+ ?^ decimal-y [%| u.decimal-y]
8732 [%| ["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)]]]]
9502 [%| ["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)]]]]
8733− [%& typ.p.left state.p.right(sub u.joined)]
9503+ [%& typ.u.joined state.p.right(sub sub.u.joined)]
8734 %cast
9504 %cast
8735 =/ target=(unit [typ=itype state=istate]) (infer-simple-shape shape.e state)
9505 =/ target=(unit [typ=itype state=istate]) (infer-simple-shape shape.e state)
8736 ?~ target
9506 ?~ target
@@ -8750,6 +9520,8 @@
8750 ?^ missing [%| u.missing]
9520 ?^ missing [%| u.missing]
8751 =/ 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)
9521 =/ 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)
8752 ?^ nested [%| u.nested]
9522 ?^ nested [%| u.nested]
9523+ =/ decimal=(unit idiag) (decimal-misfit val.e typ.p.value typ.u.target sub.state.p.value next.state.p.value)
9524+ ?^ decimal [%| u.decimal]
8753 [%| ["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)]]]]
9525 [%| ["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)]]]]
8754 ?: &(?=(^ defer.state.p.value) !(dg-stable-fit typ.p.value typ.u.target sub.fit))
9526 ?: &(?=(^ defer.state.p.value) !(dg-stable-fit typ.p.value typ.u.target sub.fit))
8755 [%| ["deferred cast fit needs stable inference" ~]]
9527 [%| ["deferred cast fit needs stable inference" ~]]
@@ -8778,6 +9550,7 @@
8778 ?~ args.e [%| ["call has no argument" ~]]
9550 ?~ args.e [%| ["call has no argument" ~]]
8779 ?: (explicit-proj-call e env state)
9551 ?: (explicit-proj-call e env state)
8780 [%| ["proj needs an expected record type" ~]]
9552 [%| ["proj needs an expected record type" ~]]
9553+ ?: (reserved-call %unface e env state) (infer-unface e env state)
8781 (infer-call-with-head e env state (infer-fragment head.e env state))
9554 (infer-call-with-head e env state (infer-fragment head.e env state))
8782 * [%| ["expression is not supported by partial inference" ~]]
9555 * [%| ["expression is not supported by partial inference" ~]]
8783 ==
9556 ==
@@ -9073,11 +9846,17 @@
9073 ?^ missing [%| u.missing]
9846 ?^ missing [%| u.missing]
9074 =/ nested=(unit idiag) (nested-missing-tag i.args.e typ.p.arg sample.ht sub.st next.st (span-of head.e))
9847 =/ nested=(unit idiag) (nested-missing-tag i.args.e typ.p.arg sample.ht sub.st next.st (span-of head.e))
9075 ?^ nested [%| u.nested]
9848 ?^ nested [%| u.nested]
9849+ =/ decimal=(unit idiag) (decimal-misfit i.args.e typ.p.arg sample.ht sub.st next.st)
9850+ ?^ decimal [%| u.decimal]
9076 [%| ["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)]]]]
9851 [%| ["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)]]]]
9077 =/ bad=(unit [at=span typ=itype])
9852 =/ bad=(unit [at=span typ=itype])
9078 (call-error-site args.e typ.p.arg sample.ht sub.st next.st)
9853 (call-error-site args.e typ.p.arg sample.ht sub.st next.st)
9079 =/ whole-args=span
9854 =/ whole-args=span
9080 [beg:(span-of i.args.e) end:(span-of (rear args.e))]
9855 [beg:(span-of i.args.e) end:(span-of (rear args.e))]
9856+ =/ decimal=(unit idiag)
9857+ =/ items=(list item) (turn args.e |=(a=expr [(span-of a) ~ a]))
9858+ (decimal-misfit [%tuple whole-args items] typ.p.arg sample.ht sub.st next.st)
9859+ ?^ decimal [%| u.decimal]
9081 =/ arg-at=span ?~(bad whole-args at.u.bad)
9860 =/ arg-at=span ?~(bad whole-args at.u.bad)
9082 =/ arg-type=itype ?~(bad typ.p.arg typ.u.bad)
9861 =/ arg-type=itype ?~(bad typ.p.arg typ.u.bad)
9083 [%| ["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)]]]]
9862 [%| ["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)]]]]
@@ -9148,6 +9927,8 @@
9148 ?^ missing [%| u.missing]
9927 ?^ missing [%| u.missing]
9149 =/ nested=(unit idiag) (nested-missing-tag val.e typ.p.value payload sub.state.p.value next.state.p.value context)
9928 =/ nested=(unit idiag) (nested-missing-tag val.e typ.p.value payload sub.state.p.value next.state.p.value context)
9150 ?^ nested [%| u.nested]
9929 ?^ nested [%| u.nested]
9930+ =/ decimal=(unit idiag) (decimal-misfit val.e typ.p.value payload sub.state.p.value next.state.p.value)
9931+ ?^ decimal [%| u.decimal]
9151 [%| ["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)]]]]
9932 [%| ["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)]]]]
9152 [%& expected state.p.value(sub sub.fit, next next.fit)]
9933 [%& expected state.p.value(sub sub.fit, next next.fit)]
9153::
9934::
@@ -9160,6 +9941,7 @@
9160 ^- iresult
9941 ^- iresult
9161 ?> ?=(%call -.e)
9942 ?> ?=(%call -.e)
9162 ?~ args.e [%| ["call has no argument" ~]]
9943 ?~ args.e [%| ["call has no argument" ~]]
9944+ ?: (reserved-call %unface e env state) (infer-unface e env state)
9163 =/ head=iresult (infer-fragment head.e env state)
9945 =/ head=iresult (infer-fragment head.e env state)
9164 ?: ?=(%| -.head) head
9946 ?: ?=(%| -.head) head
9165 =/ ht=itype (itype-walk typ.p.head sub.state.p.head)
9947 =/ ht=itype (itype-walk typ.p.head sub.state.p.head)
@@ -9242,18 +10024,70 @@
9242 `(infer-simple-items items.e env state)
10024 `(infer-simple-items items.e env state)
9243 `(width-infer-items items.e index.u.target env state context)
10025 `(width-infer-items items.e index.u.target env state context)
9244::
10026::
10027+:: +reserved-call: whether e calls the reserved operation n
10028+::
9245−:: Experimental intrinsic recognition; real bindings retain normal calls.
10029+:: Experimental intrinsic recognition; real bindings retain normal calls.
10030+++ reserved-call
10031+ |= [n=term e=expr env=ienv state=istate]
10032+ ^- ?
10033+ ?. ?=(%call -.e) |
10034+ ?. ?=(%wing -.head.e) |
10035+ ?. =(names.head.e ~[n]) |
10036+ ?: ?=(^ (ienv-lookup n env)) |
10037+ ?: (lien globals.state |=(x=term =(x n))) |
10038+ ?~ prelude.state &
10039+ ?:(?=(^ (ienv-lookup n values.u.prelude.state)) | &)
9246++ explicit-proj-call
10040++ explicit-proj-call
9247 |= [e=expr env=ienv state=istate]
10041 |= [e=expr env=ienv state=istate]
9248 ^- ?
10042 ^- ?
9249 ?. ?=(%call -.e) |
10043 ?. ?=(%call -.e) |
9250 ?. ?=([* ~] args.e) |
10044 ?. ?=([* ~] args.e) |
9251− ?. ?=(%wing -.head.e) |
10045+ (reserved-call %proj e env state)
9252− ?. =(names.head.e ~[%proj]) |
10046+::
9253− ?: ?=(^ (ienv-lookup %proj env)) |
10047+:: +infer-unface: (unface e), e's type with every face removed
9254− ?: (lien globals.state |=(n=term =(n %proj))) |
10048+::
9255− ?~ prelude.state &
10049+:: A reserved operation handled by type, like proj. Any number of
9256− ?:(?=(^ (ienv-lookup %proj values.u.prelude.state)) | &)
10050+:: arguments is taken here so that a wrong count is an error. A type
10051+:: not yet known would wait, as wing access does; the partial checker
10052+:: has no such wait and reports it as unsupported, as it does field
10053+:: access on such a type.
10054+++ infer-unface
10055+ |= [e=expr env=ienv state=istate]
10056+ ^- iresult
10057+ ?> ?=(%call -.e)
10058+ ?. ?=([* ~] args.e)
10059+ [%| ["unface takes one argument, as (unface e)" ~[[at.e "unface call"]]]]
10060+ ?^ defer.state [%| ["deferred unface needs unsupported inference" ~]]
10061+ =/ value=iresult (infer-fragment i.args.e env state)
10062+ ?: ?=(%| -.value) value
10063+ =/ typ=itype (itype-walk typ.p.value sub.state.p.value)
10064+ ?: ?=(?(%var %fvar) -.typ)
10065+ [%| ["unface on a type not yet known is not supported by partial inference" ~]]
10066+ [%& (itype-unface typ sub.state.p.value) state.p.value]
10067+::
10068+:: +unface-value: the error for unface written where a value goes
10069+::
10070+++ unface-value
10071+ |= at=span
10072+ ^- idiag
10073+ ["unface is not a value; write |=(g (unface g))" ~[[at "unface used as a value"]]]
10074+::
10075+:: +unfaced-gate: the gate under a ++'s (unface |= …), or ~
10076+::
10077+:: Such a ++ is a gate for recursion: its own name has the unfaced
10078+:: type, and its body may call it.
10079+++ unfaced-gate
10080+ |= [e=expr env=ienv state=istate]
10081+ ^- (unit expr)
10082+ ?: ?=(%group -.e) $(e inner.e)
10083+ ?. (reserved-call %unface e env state) ~
10084+ ?> ?=(%call -.e)
10085+ ?. ?=([* ~] args.e) ~
10086+ =/ gate=expr i.args.e
10087+ |-
10088+ ?: ?=(%group -.gate) $(gate inner.gate)
10089+ ?. ?=(?(%gate %gate-wide) -.gate) ~
10090+ `gate
9257++ infer-proj-source
10091++ infer-proj-source
9258 |= [e=expr expected=itype env=ienv state=istate context=span]
10092 |= [e=expr expected=itype env=ienv state=istate context=span]
9259 ^- iresult
10093 ^- iresult
@@ -9516,6 +10350,8 @@
9516 ?: ?=(%bad -.fit) [%| ["recursive mold cell does not fit its source shape" ~]]
10350 ?: ?=(%bad -.fit) [%| ["recursive mold cell does not fit its source shape" ~]]
9517 [%& target state.p.value(sub sub.fit, next next.fit)]
10351 [%& target state.p.value(sub sub.fit, next next.fit)]
9518 ?: ?=(%call -.e) (infer-contextual-call e target env state)
10352 ?: ?=(%call -.e) (infer-contextual-call e target env state)
10353+ =/ named=(unit idiag) (branch-tag-name e env state)
10354+ ?^ named [%| u.named]
9519 =/ empty-list=(unit iresult) (empty-list-null-branch e env state `[target context])
10355 =/ empty-list=(unit iresult) (empty-list-null-branch e env state `[target context])
9520 ?^ empty-list u.empty-list
10356 ?^ empty-list u.empty-list
9521 ?: (single-structured-pattern e)
10357 ?: (single-structured-pattern e)
@@ -9658,7 +10494,7 @@
9658 ?~ pats [%& ~]
10494 ?~ pats [%& ~]
9659 ?. ?=(%bind -.i.pats) [%| 'branch pattern is not supported by partial inference']
10495 ?. ?=(%bind -.i.pats) [%| 'branch pattern is not supported by partial inference']
9660 =/ name=term name.i.pats
10496 =/ name=term name.i.pats
9661− ?: |(=(name %proj) ?=(^ (ienv-lookup name env)) (lien globals |=(n=term =(n name))) (lien seen |=(n=term =(n name))))
10497+ ?: |((reserved-name name) ?=(^ (ienv-lookup name env)) (lien globals |=(n=term =(n name))) (lien seen |=(n=term =(n name))))
9662 [%| 'pattern shadows a name']
10498 [%| 'pattern shadows a name']
9663 =/ rest=(each (list term) @t) $(pats t.pats, seen [name seen])
10499 =/ rest=(each (list term) @t) $(pats t.pats, seen [name seen])
9664 ?: ?=(%| -.rest) rest
10500 ?: ?=(%| -.rest) rest
@@ -9735,24 +10571,12 @@
9735 ^- tape
10571 ^- tape
9736 =. t (itype-walk t sub)
10572 =. t (itype-walk t sub)
9737 ?- -.t
10573 ?- -.t
9738− %var
10574+ %var (show-var id.t)
9739− ?: (lth id.t 26) [(add 65 id.t) ~]
9740− "T{<id.t>}"
9741− %fvar
10575+ %fvar (show-var id.t)
9742− ?: (lth id.t 26) [(add 65 id.t) ~]
9743− "T{<id.t>}"
9744− %avar
10576+ %avar (show-var id.t)
9745− ?: (lth id.t 26) [(add 65 id.t) ~]
9746− "T{<id.t>}"
9747− %rvar
10577+ %rvar (show-var id.t)
9748− ?: (lth id.t 26) [(add 65 id.t) ~]
9749− "T{<id.t>}"
9750− %nvar
10578+ %nvar (show-var id.t)
9751− ?: (lth id.t 26) [(add 65 id.t) ~]
9752− "T{<id.t>}"
9753− %rnvar
10579+ %rnvar (show-var id.t)
9754− ?: (lth id.t 26) [(add 65 id.t) ~]
9755− "T{<id.t>}"
9756 %atom "@{(trip aura.t)}"
10580 %atom "@{(trip aura.t)}"
9757 %any-atom "@"
10581 %any-atom "@"
9758 %flag "?"
10582 %flag "?"
@@ -9773,6 +10597,17 @@
9773 %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
10597 %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
9774 ==
10598 ==
9775::
10599::
10600+:: +show-var: a type variable as printed: its name if it has one, else
10601+:: a letter for its number, A to Z, then T26, T27 and on
10602+::
10603+++ show-var
10604+ |= id=@ud
10605+ ^- tape
10606+ =/ name=@t (var-name id)
10607+ ?. =(0 name) (trip name)
10608+ ?: (lth id 26) [(add 65 id) ~]
10609+ "T{<id>}"
10610+::
9776++ show-itype-item
10611++ show-itype-item
9777 |= [t=itype sub=isub]
10612 |= [t=itype sub=isub]
9778 ^- tape
10613 ^- tape
@@ -9831,8 +10666,7 @@
9831 ?: |(?=(%var -.normalized) ?=(%fvar -.normalized) ?=(%avar -.normalized) ?=(%rvar -.normalized) (itype-has-nvar normalized) (itype-has-tag normalized) (itype-has-union normalized)) label
10666 ?: |(?=(%var -.normalized) ?=(%fvar -.normalized) ?=(%avar -.normalized) ?=(%rvar -.normalized) (itype-has-nvar normalized) (itype-has-tag normalized) (itype-has-union normalized)) label
9832 ?: (itype-has-hidden-recursive normalized) label
10667 ?: (itype-has-hidden-recursive normalized) label
9833 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
10668 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
9834− ?: (gth (lent vars) 26) label
9835− =/ printable=itype (canonical-itype normalized vars)
10669+ =/ printable=itype (canonical-itype (cap-names normalized vars ~ sub))
9836 "{label} has type {(show-itype printable ~)}{(show-atom-constraint printable)}"
10670 "{label} has type {(show-itype printable ~)}{(show-atom-constraint printable)}"
9837::
10671::
9838:: A capital in a written mold is generalized with its enclosing ++.
10672:: A capital in a written mold is generalized with its enclosing ++.
@@ -9873,6 +10707,116 @@
9873 ?: =(n u.ident) `i.caps
10707 ?: =(n u.ident) `i.caps
9874 $(caps t.caps)
10708 $(caps t.caps)
9875::
10709::
10710+:: +cap-names: give each variable in vars the name it was written with
10711+::
10712+:: Unification joins variables, and the one an ID resolves to may not
10713+:: carry the name its definition wrote, as when a capital meets a
10714+:: called gate's variable or an atom variable. Each variable in vars
10715+:: takes the name of the first capital in caps that resolves to it;
10716+:: failing that, of the earliest made of the named variables that
10717+:: resolve to it, itself included (+joined-names). Only the name part
10718+:: of an ID changes, not its count, so IDs stay distinct.
10719+::
10720+++ cap-names
10721+ |= [typ=itype vars=(list @ud) caps=icaps sub=isub]
10722+ ^- [typ=itype vars=(list @ud)]
10723+ =/ written=icaps (flop caps)
10724+ =/ joined=(map @ud @ud) (joined-names sub)
10725+ =/ ren=(map @ud @ud) ~
10726+ =/ out=(list @ud) ~
10727+ |-
10728+ ?~ vars [?~(ren typ (itype-reid typ ren)) (flop out)]
10729+ =/ cap=(unit icap) (cap-with-id i.vars written sub)
10730+ =/ first=(unit @ud) (~(get by joined) i.vars)
10731+ =/ name=@t
10732+ ?^ cap name.u.cap
10733+ ?~ first (var-name i.vars)
10734+ ?: =(0 (var-name i.vars)) (var-name u.first)
10735+ ?: (lth (var-count u.first) (var-count i.vars)) (var-name u.first)
10736+ (var-name i.vars)
10737+ =/ to=@ud (named-var name i.vars)
10738+ ?: =(to i.vars) $(vars t.vars, out [i.vars out])
10739+ $(vars t.vars, out [to out], ren (~(put by ren) i.vars to))
10740+::
10741+:: +joined-names: for each variable that named ones resolve to, the
10742+:: earliest made of those, by count
10743+::
10744+:: One pass over sub keeps each ID's newest binding, as +itype-lookup
10745+:: would find it: the variable it is bound to, or ~ for another type.
10746+:: Each named ID then follows those bindings to the variable it
10747+:: resolves to, if any.
10748+::
10749+++ joined-names
10750+ |= sub=isub
10751+ ^- (map @ud @ud)
10752+ =/ edges=(map @ud (unit @ud))
10753+ %+ roll (flop sub)
10754+ |= [b=ibinding m=(map @ud (unit @ud))]
10755+ (~(put by m) id.b (var-of val.b))
10756+ =/ named=(list @ud)
10757+ (murn ~(tap by edges) |=([k=@ud *] ?:(=(0 (var-name k)) ~ `k)))
10758+ =/ fuel=@ud ~(wyt by edges)
10759+ =/ out=(map @ud @ud) ~
10760+ |-
10761+ ?~ named out
10762+ =/ root=(unit @ud) (follow-var i.named edges fuel)
10763+ ?~ root $(named t.named)
10764+ ?: =(u.root i.named) $(named t.named)
10765+ =/ best=(unit @ud) (~(get by out) u.root)
10766+ ?: &(?=(^ best) (lth (var-count u.best) (var-count i.named)))
10767+ $(named t.named)
10768+ $(named t.named, out (~(put by out) u.root i.named))
10769+::
10770+:: +follow-var: the variable that id resolves to through edges, or ~ if
10771+:: it resolves to another type; fuel bounds the steps
10772+::
10773+++ follow-var
10774+ |= [id=@ud edges=(map @ud (unit @ud)) fuel=@ud]
10775+ ^- (unit @ud)
10776+ |-
10777+ ?: =(0 fuel) ~
10778+ =/ edge=(unit (unit @ud)) (~(get by edges) id)
10779+ ?~ edge `id
10780+ ?~ u.edge ~
10781+ ?: =(u.u.edge id) `id
10782+ $(id u.u.edge, fuel (dec fuel))
10783+::
10784+:: +var-of: the ID of a type variable node, or ~ for another type
10785+::
10786+++ var-of
10787+ |= t=itype
10788+ ^- (unit @ud)
10789+ ?+ -.t ~
10790+ %var `id.t
10791+ %fvar `id.t
10792+ %avar `id.t
10793+ %rvar `id.t
10794+ %nvar `id.t
10795+ %rnvar `id.t
10796+ ==
10797+::
10798+:: +itype-reid: t with the variable IDs in ids replaced, each node
10799+:: keeping its kind
10800+::
10801+++ itype-reid
10802+ |= [t=itype ids=(map @ud @ud)]
10803+ ^- itype
10804+ ?- -.t
10805+ %var t(id (fall (~(get by ids) id.t) id.t))
10806+ %fvar t(id (fall (~(get by ids) id.t) id.t))
10807+ %avar t(id (fall (~(get by ids) id.t) id.t))
10808+ %rvar t(id (fall (~(get by ids) id.t) id.t))
10809+ %nvar t(id (fall (~(get by ids) id.t) id.t))
10810+ %rnvar t(id (fall (~(get by ids) id.t) id.t))
10811+ ?(%atom %any-atom %flag %noun %empty %tag %const %recursive %jrec) t
10812+ %union t(cases (turn cases.t |=(c=itype ^$(t c))), args (turn args.t |=(c=itype ^$(t c))))
10813+ %grec t(args (turn args.t |=(c=itype ^$(t c))))
10814+ %collection t(args (turn args.t |=(c=itype ^$(t c))))
10815+ %face t(body $(t body.t))
10816+ %fn t(sample $(t sample.t), product $(t product.t))
10817+ %cell t(hed $(t hed.t), tal $(t tal.t))
10818+ ==
10819+::
9876++ merged-capitals
10820++ merged-capitals
9877 |= [caps=icaps sub=isub]
10821 |= [caps=icaps sub=isub]
9878 ^- (unit [first=icap second=icap])
10822 ^- (unit [first=icap second=icap])
@@ -9995,9 +10939,10 @@
9995 $(vars t.vars)
10939 $(vars t.vars)
9996::
10940::
9997:: Build the supported part of the value environment in dependency order.
10941:: Build the supported part of the value environment in dependency order.
9998−:: Each pass adds successful definitions. Forward references become
10942+:: Each pass adds successful definitions, visiting them dependencies first
9999−:: available on a later pass; unsupported syntax does not enter the
10943+:: (+dependency-order), so a forward reference usually resolves in the
10944+:: first pass; any that do not are retried on a later pass. Unsupported
10000−:: environment. Generalized definitions are closed, so a use instantiates
10945+:: syntax does not enter the environment. Generalized definitions are closed, so a use instantiates
10001:: its variables afresh.
10946:: its variables afresh.
10002::
10947::
10003++ global-value-names
10948++ global-value-names
@@ -10091,6 +11036,9 @@
10091 ?^ defer.state [%| ["deferred recursive inference is unsupported" ~]]
11036 ?^ defer.state [%| ["deferred recursive inference is unsupported" ~]]
10092 =. gate-defs.state ~
11037 =. gate-defs.state ~
10093 ?. ?=(%value -.d) [%| ["recursive definition is not a gate" ~]]
11038 ?. ?=(%value -.d) [%| ["recursive definition is not a gate" ~]]
11039+ :: A ++ whose body is (unface |= …) is a gate too, unfaced
11040+ =/ peeled=(unit expr) (unfaced-gate val.d env state)
11041+ =? val.d ?=(^ peeled) u.peeled
10094 ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d))
11042 ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d))
10095 [%| ["recursive definition is not a gate" ~]]
11043 [%| ["recursive definition is not a gate" ~]]
10096 =/ result=(unit itype) (recursive-branch-seed d env state)
11044 =/ result=(unit itype) (recursive-branch-seed d env state)
@@ -10114,6 +11062,7 @@
10114 =/ product=itype ?~(result [%var id] u.result)
11062 =/ product=itype ?~(result [%var id] u.result)
10115 =/ st=istate state.p.sam(next +(id))
11063 =/ st=istate state.p.sam(next +(id))
10116 =/ seed=itype [%fn typ.p.sam product]
11064 =/ seed=itype [%fn typ.p.sam product]
11065+ =? seed ?=(^ peeled) (itype-unface seed sub.st)
10117 =/ seeded=ienv [[name.d [seed ~]] env.p.sam]
11066 =/ seeded=ienv [[name.d [seed ~]] env.p.sam]
10118 =/ body=expr
11067 =/ body=expr
10119 ?- -.gate
11068 ?- -.gate
@@ -10125,7 +11074,9 @@
10125 ?: ?=(%| -.out) out
11074 ?: ?=(%| -.out) out
10126 =/ uni=(unit isub) (itype-unify product typ.p.out sub.state.p.out)
11075 =/ uni=(unit isub) (itype-unify product typ.p.out sub.state.p.out)
10127 ?~ uni [%| ["recursive gate constraint is not supported by partial inference" ~]]
11076 ?~ uni [%| ["recursive gate constraint is not supported by partial inference" ~]]
11077+ =/ typ=itype [%fn typ.p.sam typ.p.out]
11078+ =? typ ?=(^ peeled) (itype-unface typ u.uni)
10128− [%& [%fn typ.p.sam typ.p.out] state.p.out(sub u.uni)]
11079+ [%& typ state.p.out(sub u.uni)]
10129::
11080::
10130++ dependency-root
11081++ dependency-root
10131 |= names=(list term)
11082 |= names=(list term)
@@ -10233,7 +11184,7 @@
10233:: Infer a cyclic component with one monomorphic seed per gate. All members
11184:: Infer a cyclic component with one monomorphic seed per gate. All members
10234:: must succeed before any scheme is available; pending constraints and
11185:: must succeed before any scheme is available; pending constraints and
10235:: unresolved branch joins remain partial.
11186:: unresolved branch joins remain partial.
10236−+$ igate-entry [name=term typ=itype body=expr env=ienv caps=icaps]
11187++$ igate-entry [name=term typ=itype body=expr env=ienv caps=icaps unfaced=?]
10237+$ igate-seeds (each [entries=(list igate-entry) state=istate] idiag)
11188+$ igate-seeds (each [entries=(list igate-entry) state=istate] idiag)
10238++ seed-gate-group
11189++ seed-gate-group
10239 |= [ds=(list def) env=ienv state=istate]
11190 |= [ds=(list def) env=ienv state=istate]
@@ -10241,7 +11192,9 @@
10241 ?~ ds [%& [~ state]]
11192 ?~ ds [%& [~ state]]
10242 =/ d=def i.ds
11193 =/ d=def i.ds
10243 ?. ?=(%value -.d) [%| ["recursive group contains a non-gate" ~]]
11194 ?. ?=(%value -.d) [%| ["recursive group contains a non-gate" ~]]
11195+ :: A ++ whose body is (unface |= …) is a gate too, unfaced
11196+ =/ peeled=(unit expr) (unfaced-gate val.d env state)
10244− =/ gate=expr val.d
11197+ =/ gate=expr ?~(peeled val.d u.peeled)
10245 ?. |(?=(%gate -.gate) ?=(%gate-wide -.gate))
11198 ?. |(?=(%gate -.gate) ?=(%gate-wide -.gate))
10246 [%| ["recursive group contains a non-gate" ~]]
11199 [%| ["recursive group contains a non-gate" ~]]
10247 =/ initial=istate (reserve-def-caps gate state)
11200 =/ initial=istate (reserve-def-caps gate state)
@@ -10259,7 +11212,8 @@
10259 * !!
11212 * !!
10260 ==
11213 ==
10261 =/ seed=itype [%fn typ.p.sam [%var next.state.p.sam]]
11214 =/ seed=itype [%fn typ.p.sam [%var next.state.p.sam]]
11215+ =? seed ?=(^ peeled) (itype-unface seed sub.state.p.sam)
10262− =/ entry=igate-entry [name.d seed body env.p.sam caps.state.p.sam]
11216+ =/ entry=igate-entry [name.d seed body env.p.sam caps.state.p.sam ?=(^ peeled)]
10263 =/ after=istate state.p.sam(next +(next.state.p.sam), caps caps.state)
11217 =/ after=istate state.p.sam(next +(next.state.p.sam), caps caps.state)
10264 =/ rest=igate-seeds $(ds t.ds, state after)
11218 =/ rest=igate-seeds $(ds t.ds, state after)
10265 ?: ?=(%| -.rest) rest
11219 ?: ?=(%| -.rest) rest
@@ -10299,16 +11253,16 @@
10299 ?: (constrained-capitals caps.entry sub.state)
11253 ?: (constrained-capitals caps.entry sub.state)
10300 [%| ["explicit capital constraints are not supported by partial inference" ~]]
11254 [%| ["explicit capital constraints are not supported by partial inference" ~]]
10301 =/ typ=itype (itype-normalize typ.entry sub.state)
11255 =/ typ=itype (itype-normalize typ.entry sub.state)
11256+ =? typ unfaced.entry (itype-unface typ ~)
10302 ?: (itype-has-nvar typ) [%| ["recursive group needs unsupported inference" ~]]
11257 ?: (itype-has-nvar typ) [%| ["recursive group needs unsupported inference" ~]]
10303 ?: |((itype-has-tag typ) (itype-has-hidden-generic typ) (itype-has-hidden-recursive typ) (unsupported-atom-vars typ caps.entry binders.state sub.state))
11258 ?: |((itype-has-tag typ) (itype-has-hidden-generic typ) (itype-has-hidden-recursive typ) (unsupported-atom-vars typ caps.entry binders.state sub.state))
10304 [%| ["recursive group needs unsupported inference" ~]]
11259 [%| ["recursive group needs unsupported inference" ~]]
10305 =/ free=(list @ud) (weld (free-env-vars env sub.state) (free-cap-vars caps.outer sub.state))
11260 =/ free=(list @ud) (weld (free-env-vars env sub.state) (free-cap-vars caps.outer sub.state))
10306 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
11261 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
10307 =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
11262 =. vars (skim vars |=(n=@ud !(lien free |=(f=@ud =(f n)))))
10308− ?: (gth (lent vars) 26) [%| ["recursive group needs too many type variables" ~]]
10309 =/ rest=(each ienv idiag) $(entries t.entries)
11263 =/ rest=(each ienv idiag) $(entries t.entries)
10310 ?: ?=(%| -.rest) rest
11264 ?: ?=(%| -.rest) rest
10311− [%& [[name.entry [typ vars]] p.rest]]
11265+ [%& [[name.entry (cap-names typ vars caps.entry sub.state)] p.rest]]
10312::
11266::
10313++ infer-gate-group
11267++ infer-gate-group
10314 |= [ds=(list def) env=ienv state=istate]
11268 |= [ds=(list def) env=ienv state=istate]
@@ -10484,14 +11438,13 @@
10484 ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ)) ~
11438 ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ)) ~
10485 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result) ~
11439 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result) ~
10486 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
11440 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
10487− ?: (gth (lent vars) 26) ~
10488 =/ finalized=(unit (list iwprojection))
11441 =/ finalized=(unit (list iwprojection))
10489 (width-finalize projections.state.p.result sub.state.p.result vars)
11442 (width-finalize projections.state.p.result sub.state.p.result vars)
10490 ?~ finalized ~
11443 ?~ finalized ~
10491 =? artifacts ?=(^ u.finalized)
11444 =? artifacts ?=(^ u.finalized)
10492 [[name.d val.d typ sub.state.p.result (flop u.finalized)] artifacts]
11445 [[name.d val.d typ sub.state.p.result (flop u.finalized)] artifacts]
10493 =? checked |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) (~(put by checked) name.d d)
11446 =? checked |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) (~(put by checked) name.d d)
10494− `[[[name.d [typ vars]] env] checked artifacts]
11447+ `[[[name.d (cap-names typ vars caps.state.p.result sub.state.p.result)] env] checked artifacts]
10495++ add-supported-defs-core
11448++ add-supported-defs-core
10496 |= [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)])]
11449 |= [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)])]
10497 ^- [env=ienv artifacts=(list iwidth-definition)]
11450 ^- [env=ienv artifacts=(list iwidth-definition)]
@@ -10550,15 +11503,38 @@
10550 =/ components=icomponents (graph-components ds names)
11503 =/ components=icomponents (graph-components ds names)
10551 =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11504 =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
10552 =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude)
11505 =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude)
11506+ =/ ordered=(list def) (dependency-order ds components)
10553 |-
11507 |-
10554 =/ next=[env=ienv artifacts=(list iwidth-definition)]
11508 =/ next=[env=ienv artifacts=(list iwidth-definition)]
10555− (add-supported-defs-core ds (direct-checked-gates ds env) heads env molds globals externals surs mark-externals marks jimports reserved-molds at prelude artifacts index)
11509+ (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)
10556 =/ initial=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ | at top prelude ~ 256 ~ ~ ~ ~ ~ ~]
11510 =/ initial=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ | at top prelude ~ 256 ~ ~ ~ ~ ~ ~]
10557 =. grec-index.initial index
11511 =. grec-index.initial index
10558 =/ out=iresolved (add-groups ds components graph env.next grouped artifacts.next initial)
11512 =/ out=iresolved (add-groups ds components graph env.next grouped artifacts.next initial)
10559 ?: =(env env.out) out
11513 ?: =(env env.out) out
10560 $(env env.out, grouped grouped.out, artifacts artifacts.out)
11514 $(env env.out, grouped grouped.out, artifacts artifacts.out)
10561::
11515::
11516+:: +dependency-order: the value definitions, dependencies first
11517+::
11518+:: +graph-components lists the components dependencies first, so one
11519+:: pass of +add-supported-defs-core in this order resolves a forward
11520+:: chain that would otherwise take a pass per link; the fixpoint above
11521+:: stays as the fallback (review question 12). Members of a component
11522+:: keep their source order. Definitions in no component (molds, and
11523+:: every value when duplicate names leave no components) follow in
11524+:: source order.
11525+::
11526+++ dependency-order
11527+ |= [ds=(list def) components=icomponents]
11528+ ^- (list def)
11529+ =/ ranked=(list def)
11530+ %- zing
11531+ %+ turn components
11532+ |= component=(list term)
11533+ (skim ds |=(d=def &(?=(%value -.d) (lien component |=(n=term =(n name.d))))))
11534+ =/ members=(list term) (zing components)
11535+ =/ named=ivisited (graph-nameset members ~)
11536+ (weld ranked (skip ds |=(d=def &(?=(%value -.d) (~(has by named) name.d)))))
11537+::
10562++ resolve-supported-defs
11538++ resolve-supported-defs
10563 |= [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)]
11539 |= [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)]
10564 ^- ienv
11540 ^- ienv
@@ -11067,6 +12043,22 @@
11067 [at.first at.second (union-relate a (project-union-mold second molds ~))]
12043 [at.first at.second (union-relate a (project-union-mold second molds ~))]
11068 (weld pairs $(cases t.cases))
12044 (weld pairs $(cases t.cases))
11069::
12045::
12046+:: The partial report and the full module check share one overlap proof,
12047+:: so for the same union both name the same pair. The caller passes the
12048+:: projected .pairs, which the partial report reads again. The projection
12049+:: proves atoms, flags and nested literal cells, and its first overlap is
12050+:: named even when the source slice would prove an earlier pair. The
12051+:: source slice is tried only when some pair is unknown, for its one-hop
12052+:: generic applications. A missing witness does not mean the cases are
12053+:: disjoint.
12054+++ mold-overlap-witness
12055+ |= [cases=(list shape) pairs=(list upair) molds=imolds]
12056+ ^- (unit upair)
12057+ =/ overlapping=(list upair) (skim pairs |=(p=upair =(%overlap relation.p)))
12058+ ?^ overlapping `i.overlapping
12059+ ?. (lien pairs |=(p=upair =(%unknown relation.p))) ~
12060+ (union-source-overlap cases molds 256)
12061+::
11070:: A closed structural mold supplies no equation to determine a hole.
12062:: A closed structural mold supplies no equation to determine a hole.
11071:: Applications, references, unbound capitals and unions are unproved.
12063:: Applications, references, unbound capitals and unions are unproved.
11072++ simple-mold-hole
12064++ simple-mold-hole
@@ -11206,14 +12198,9 @@
11206 =? sh ?=(%generic -.sh) body.sh
12198 =? sh ?=(%generic -.sh) body.sh
11207 ?. ?=(%union -.sh) (crip "+$ {(trip name.d)}: not checked")
12199 ?. ?=(%union -.sh) (crip "+$ {(trip name.d)}: not checked")
11208 =/ pairs=(list upair) (union-pairs cases.sh molds)
12200 =/ pairs=(list upair) (union-pairs cases.sh molds)
11209− =/ overlapping=(list upair) (skim pairs |=(p=upair =(%overlap relation.p)))
11210− =. overlapping
11211− ?^ overlapping overlapping
11212− ?. (lien pairs |=(p=upair =(%unknown relation.p))) ~
11213− =/ witness=(unit upair) (union-source-overlap cases.sh molds 256)
12201+ =/ witness=(unit upair) (mold-overlap-witness cases.sh pairs molds)
11214− ?~(witness ~ ~[u.witness])
12202+ ?^ witness
11215− ?^ overlapping
12203+ =/ p=upair u.witness
11216− =/ p=upair i.overlapping
11217 =/ summary=@t (crip "+$ {(trip name.d)}: overlapping cases; mold not checked")
12204 =/ summary=@t (crip "+$ {(trip name.d)}: overlapping cases; mold not checked")
11218 =/ first=@t (show-error src [file line.beg.first.p col.beg.first.p "first union case"])
12205 =/ first=@t (show-error src [file line.beg.first.p col.beg.first.p "first union case"])
11219 =/ second=@t (show-error src [file line.beg.second.p col.beg.second.p "overlapping case"])
12206 =/ second=@t (show-error src [file line.beg.second.p col.beg.second.p "overlapping case"])
@@ -11237,6 +12224,7 @@
11237 (of-wain:format [summary excerpts])
12224 (of-wain:format [summary excerpts])
11238::
12225::
11239:: Both written field sites are shown in the source that declares them.
12226:: Both written field sites are shown in the source that declares them.
12227+:: A store's derived-name clash shows its two sites the same way.
11240++ show-duplicate-fields
12228++ show-duplicate-fields
11241 |= [file=path src=@t diagnostic=idiag]
12229 |= [file=path src=@t diagnostic=idiag]
11242 ^- @t
12230 ^- @t
@@ -11394,13 +12382,29 @@
11394 =/ first=(unit idiag) ?:(?=(%expr -.i.segs) (duplicate-expr p.i.segs) ~)
12382 =/ first=(unit idiag) ?:(?=(%expr -.i.segs) (duplicate-expr p.i.segs) ~)
11395 ?^ first first
12383 ?^ first first
11396 $(segs t.segs)
12384 $(segs t.segs)
12385+:: A change's items each set a field once: two that name the same field,
12386+:: or one a field inside the other's, as cart and open.cart, overlap.
11397++ duplicate-edits
12387++ duplicate-edits
11398 |= edits=(list edit)
12388 |= edits=(list edit)
11399 ^- (unit idiag)
12389 ^- (unit idiag)
12390+ =| seen=(list edit)
12391+ |- ^- (unit idiag)
11400 ?~ edits ~
12392 ?~ edits ~
12393+ =/ e=edit i.edits
12394+ =/ prior=(list edit)
12395+ (skim seen |=(p=edit (wing-overlap (flop names.p) (flop names.e))))
12396+ ?^ prior
12397+ =/ same=? =(names.i.prior names.e)
12398+ =/ sites=(list [at=span note=tape])
12399+ :~ [at.i.prior "first field"]
12400+ [at.e ?:(same "repeated field" "overlapping field")]
12401+ ==
12402+ ?: same `["change field `{(show-names names.e)}` is repeated" sites]
12403+ =/ a=tape (show-names names.i.prior)
12404+ `["change fields `{a}` and `{(show-names names.e)}` overlap" sites]
11401− =/ first (duplicate-expr val.i.edits)
12405+ =/ first (duplicate-expr val.e)
11402 ?^ first first
12406 ?^ first first
11403− $(edits t.edits)
12407+ $(edits t.edits, seen [e seen])
11404++ duplicate-arms
12408++ duplicate-arms
11405 |= arms=(list arm)
12409 |= arms=(list arm)
11406 ^- (unit idiag)
12410 ^- (unit idiag)
@@ -11473,59 +12477,68 @@
11473 ==
12477 ==
11474 [n $(imports t.imports)]
12478 [n $(imports t.imports)]
11475::
12479::
12480+:: +reserved-name: whether n names a reserved operation
12481+::
12482+:: proj and unface are handled by the checker by type, not bound, so
12483+:: no module may define, import or bind either name, as a value or
12484+:: as a mold. A field, tag or path segment may still be spelled so.
11476−++ reserved-proj-sample
12485+++ reserved-name
12486+ |= n=term
12487+ ^- ?
12488+ |(=(n %proj) =(n %unface))
12489+++ reserved-sample
11477 |= sam=sample
12490 |= sam=sample
11478 ^- ?
12491 ^- ?
11479 ?- -.sam
12492 ?- -.sam
11480− %bind =(name.sam %proj)
12493+ %bind (reserved-name name.sam)
11481− %face =(name.sam %proj)
12494+ %face (reserved-name name.sam)
11482− %pun =(name.sam %proj)
12495+ %pun (reserved-name name.sam)
11483− %cell (lien items.sam reserved-proj-sample)
12496+ %cell (lien items.sam reserved-sample)
11484 * |
12497 * |
11485 ==
12498 ==
11486−++ reserved-proj-pattern
12499+++ reserved-pattern
11487 |= p=pattern
12500 |= p=pattern
11488 ^- ?
12501 ^- ?
11489 ?- -.p
12502 ?- -.p
11490− %bind =(name.p %proj)
12503+ %bind (reserved-name name.p)
11491− %cell (lien items.p reserved-proj-pattern)
12504+ %cell (lien items.p reserved-pattern)
11492 * |
12505 * |
11493 ==
12506 ==
11494−++ reserved-proj-def
12507+++ reserved-def
11495 |= d=def
12508 |= d=def
11496 ^- ?
12509 ^- ?
11497− ?: =(name.d %proj) &
12510+ ?: (reserved-name name.d) &
11498− ?: ?=(%value -.d) (reserved-proj-expr val.d)
12511+ ?: ?=(%value -.d) (reserved-expr val.d)
11499 |
12512 |
11500−++ reserved-proj-expr
12513+++ reserved-expr
11501 |= e=expr
12514 |= e=expr
11502 ^- ?
12515 ^- ?
11503 ?- -.e
12516 ?- -.e
11504− %str (lien pieces.e |=(p=piece ?:(?=(%expr -.p) (reserved-proj-expr p.p) |)))
12517+ %str (lien pieces.e |=(p=piece ?:(?=(%expr -.p) (reserved-expr p.p) |)))
11505− %qath (lien segs.e |=(p=qseg ?:(?=(%expr -.p) (reserved-proj-expr p.p) |)))
12518+ %qath (lien segs.e |=(p=qseg ?:(?=(%expr -.p) (reserved-expr p.p) |)))
11506− %change (lien edits.e |=(p=edit (reserved-proj-expr val.p)))
12519+ %change (lien edits.e |=(p=edit (reserved-expr val.p)))
11507 %pair $(e val.e)
12520 %pair $(e val.e)
11508 %unit $(e val.e)
12521 %unit $(e val.e)
11509 %group $(e inner.e)
12522 %group $(e inner.e)
11510− %list (lien items.e reserved-proj-expr)
12523+ %list (lien items.e reserved-expr)
11511− %tuple (lien items.e |=(i=item (reserved-proj-expr val.i)))
12524+ %tuple (lien items.e |=(i=item (reserved-expr val.i)))
11512− ?(%gate %gate-wide) |((reserved-proj-sample sample.e) $(e body.e))
12525+ ?(%gate %gate-wide) |((reserved-sample sample.e) $(e body.e))
11513 %cast $(e val.e)
12526 %cast $(e val.e)
11514− %call |($(e head.e) (lien args.e reserved-proj-expr))
12527+ %call |($(e head.e) (lien args.e reserved-expr))
11515 %trace |($(e val.e) $(e then.e))
12528 %trace |($(e val.e) $(e then.e))
11516− %branch |($(e subject.e) (lien arms.e |=(a=arm |((reserved-proj-pattern pat.a) (reserved-proj-expr val.a)))))
12529+ %branch |($(e subject.e) (lien arms.e |=(a=arm |((reserved-pattern pat.a) (reserved-expr val.a)))))
11517− %body |((lien defs.e reserved-proj-def) $(e final.e))
12530+ %body |((lien defs.e reserved-def) $(e final.e))
11518 * |
12531 * |
11519 ==
12532 ==
11520::
12533::
11521−++ module-has-reserved-proj
12534+++ module-has-reserved
11522 |= mod=module
12535 |= mod=module
11523 ^- ?
12536 ^- ?
11524 =/ imported=(list term) (import-binding-names imports.mod)
12537 =/ imported=(list term) (import-binding-names imports.mod)
11525 =/ vals=(list term) (global-value-names defs.mod)
12538 =/ vals=(list term) (global-value-names defs.mod)
11526 =/ molds=imolds (collect-simple-molds defs.mod)
12539 =/ molds=imolds (collect-simple-molds defs.mod)
11527 =/ mold-names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
12540 =/ mold-names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11528− |((lien (weld imported (weld vals mold-names)) |=(n=term =(n %proj))) (lien defs.mod reserved-proj-def))
12541+ |((lien (weld imported (weld vals mold-names)) reserved-name) (lien defs.mod reserved-def))
11529::
12542::
11530++ module-scope-valid
12543++ module-scope-valid
11531 |= [mod=module prelude-values=(list term) prelude-molds=(list term)]
12544 |= [mod=module prelude-values=(list term) prelude-molds=(list term)]
@@ -11534,7 +12547,7 @@
11534 =/ vals=(list term) (global-value-names defs.mod)
12547 =/ vals=(list term) (global-value-names defs.mod)
11535 =/ molds=imolds (collect-simple-molds defs.mod)
12548 =/ molds=imolds (collect-simple-molds defs.mod)
11536 =/ mold-names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
12549 =/ mold-names=(list term) (turn molds |=(m=[name=term body=shape] name.m))
11537− ?: (module-has-reserved-proj mod) |
12550+ ?: (module-has-reserved mod) |
11538 ?. %+ levy imported
12551 ?. %+ levy imported
11539 |= n=term
12552 |= n=term
11540 &((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))))
12553 &((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))))
@@ -11564,7 +12577,8 @@
11564 ?. valid ~
12577 ?. valid ~
11565 =? sh ?=(%generic -.sh) body.sh
12578 =? sh ?=(%generic -.sh) body.sh
11566 ?. ?=(%union -.sh) ~
12579 ?. ?=(%union -.sh) ~
12580+ :: A failed inference keeps no projection, so it is computed once more.
11567− (union-source-overlap cases.sh molds 256)
12581+ (mold-overlap-witness cases.sh (union-pairs cases.sh molds) molds)
11568++ module-mold-types-detail
12582++ module-mold-types-detail
11569 |= [molds=imolds state=istate]
12583 |= [molds=imolds state=istate]
11570 ^- (each imold-types imold-failure)
12584 ^- (each imold-types imold-failure)
@@ -11888,6 +12902,74 @@
11888 ?~ (ienv-lookup name.i.ds env) |
12902 ?~ (ienv-lookup name.i.ds env) |
11889 $(ds t.ds)
12903 $(ds t.ds)
11890::
12904::
12905+:: Names the value a failed full check stops at, for its message only. A
12906+:: value whose module dependencies all resolved failed on its own, so the
12907+:: first such missing value is named. Otherwise every missing value waits
12908+:: on another, so following the first one each waits on, from the first
12909+:: missing value, reaches a value twice, which is named. The walk is over
12910+:: the syntactic dependency graph: dependency-expr ignores binders, so a
12911+:: sample or other local binder with a top-level value's name reads as a
12912+:: dependency on it. The named value is on a cycle of that graph, but may
12913+:: only call into the value that failed, as when a binder in that value
12914+:: shadows the named one. It claims no error in the named value.
12915+++ module-missing-value
12916+ |= [ds=(list def) env=ienv]
12917+ ^- (unit term)
12918+ =/ missing=(list term)
12919+ %+ murn ds
12920+ |= d=def
12921+ ?. ?=(%value -.d) ~
12922+ ?^ (ienv-lookup name.d env) ~
12923+ `name.d
12924+ ?~ missing ~
12925+ =/ pending=ivisited (graph-nameset missing ~)
12926+ =/ roots=(list term)
12927+ %+ murn ds
12928+ |= d=def
12929+ ?. ?=(%value -.d) ~
12930+ ?~ (~(get by pending) name.d) ~
12931+ =/ deps=(list term) (dependency-expr val.d)
12932+ ?. (levy deps |=(n=term |(=(n name.d) ?=(~ (~(get by pending) n))))) ~
12933+ `name.d
12934+ ?^ roots `i.roots
12935+ =/ seen=ivisited ~
12936+ =/ here=term i.missing
12937+ |-
12938+ ?^ (~(get by seen) here) `here
12939+ =/ next=(list term)
12940+ %- zing
12941+ %+ turn ds
12942+ |= d=def
12943+ ?. ?=(%value -.d) ~
12944+ ?. =(here name.d) ~
12945+ (skim (dependency-expr val.d) |=(n=term &(!=(n here) ?=(^ (~(get by pending) n)))))
12946+ ?~ next `here
12947+ $(seen (~(put by seen) here &), here i.next)
12948+::
12949+:: Finds the first missing value that is a gate whose own sample has the
12950+:: name of a value in scope. Partial inference rejects that sample ("sample
12951+:: shadows a name"), and it is an error (grammar, Modules). Mark names name
12952+:: molds and are left out, as are cell samples and binders deeper in the
12953+:: value.
12954+++ module-sample-shadow
12955+ |= [ds=(list def) env=ienv values=(list term)]
12956+ ^- (unit [name=term at=span])
12957+ ?~ ds ~
12958+ ?. ?=(%value -.i.ds) $(ds t.ds)
12959+ ?^ (ienv-lookup name.i.ds env) $(ds t.ds)
12960+ =/ e=expr val.i.ds
12961+ ?. ?=(?(%gate %gate-wide) -.e) $(ds t.ds)
12962+ =/ s=sample sample.e
12963+ =/ name=(unit term)
12964+ ?+ -.s ~
12965+ %bind `name.s
12966+ %face `name.s
12967+ %pun `name.s
12968+ ==
12969+ ?~ name $(ds t.ds)
12970+ ?. (lien values |=(n=term =(n u.name))) $(ds t.ds)
12971+ `[u.name at.s]
12972+::
11891:: Cache only completed interfaces for this invocation. The source bundle,
12973:: Cache only completed interfaces for this invocation. The source bundle,
11892:: imported Hoon types and prelude are fixed for the whole graph. Check the
12974:: imported Hoon types and prelude are fixed for the whole graph. Check the
11893:: active path and duplicate sources before consulting it, so a cache hit
12975:: active path and duplicate sources before consulting it, so a cache hit
@@ -12154,10 +13236,49 @@
12154 ^- ?
13236 ^- ?
12155 =/ path-names=(list term) (turn paths |=(p=iapi-path name.p))
13237 =/ path-names=(list term) (turn paths |=(p=iapi-path name.p))
12156 =/ derived=(list term) (weld path-names poke-names)
13238 =/ derived=(list term) (weld path-names poke-names)
12157− ?: (lien derived |=(n=term =(n %proj))) |
13239+ ?: (lien derived reserved-name) |
12158 =/ outer=(list term) (weld prelude-values (weld (global-value-names defs.mod) (api-import-faces imports.mod)))
13240 =/ outer=(list term) (weld prelude-values (weld (global-value-names defs.mod) (api-import-faces imports.mod)))
12159 (levy derived |=(n=term &((unique-value-name n derived) !(lien outer |=(x=term =(n x))))))
13241 (levy derived |=(n=term &((unique-value-name n derived) !(lien outer |=(x=term =(n x))))))
12160::
13242::
13243+:: The definite error behind some failures of the check above. An API
13244+:: exports `poke` when it declares `+$ poke`, and a request per case of a
13245+:: `+$ paths` that reads as path cases; these names surely exist, so a clash
13246+:: among them or with the module's scope is an error (grammar, Modules). A
13247+:: reserved `proj` stays unsupported, as in the check above.
13248+++ api-derived-clash
13249+ |= [mod=module prelude-values=(list term)]
13250+ ^- (unit idiag)
13251+ =/ declared=(list term) (collect-mark-imports imports.mod)
13252+ =/ declarations=(list def)
13253+ (skim defs.mod |=(d=def &(?=(%mold -.d) =(%paths name.d))))
13254+ =/ cases=(list [name=term at=span note=tape])
13255+ ?. ?=([* ~] declarations) ~
13256+ =/ decl=def i.declarations
13257+ ?> ?=(%mold -.decl)
13258+ =/ paths=(unit (list iapi-path)) (api-path-declaration shape.decl declared)
13259+ ?~ paths ~
13260+ (turn u.paths |=(p=iapi-path [name.p at.p "`{(trip name.p)}` is derived from this path case"]))
13261+ =/ pokes=(list def)
13262+ (skim defs.mod |=(d=def &(?=(%mold -.d) =(%poke name.d))))
13263+ =/ derived=(list [name=term at=span note=tape])
13264+ ?. ?=([* ~] pokes) cases
13265+ (snoc cases [%poke at.i.pokes "`poke` is derived from this mold"])
13266+ =/ names=(list term) (turn derived |=(x=[name=term at=span note=tape] name.x))
13267+ =/ outer=(list term) (weld prelude-values (weld (global-value-names defs.mod) (api-import-faces imports.mod)))
13268+ =/ clashes=(list term)
13269+ %+ skip names
13270+ |= n=term
13271+ ?| (reserved-name n)
13272+ &((unique-value-name n names) !(lien outer |=(x=term =(n x))))
13273+ ==
13274+ ?~ clashes ~
13275+ =/ sites=(list [at=span note=tape])
13276+ %+ murn derived
13277+ |= x=[name=term at=span note=tape]
13278+ ?. =(i.clashes name.x) ~
13279+ `[at.x note.x]
13280+ `(derived-name-clash "API" i.clashes sites mod)
13281+::
12161:: Analysis only. Successful external entries must be unchanged results
13282:: Analysis only. Successful external entries must be unchanged results
12162:: produced for the declared marks; no request interface is produced.
13283:: produced for the declared marks; no request interface is produced.
12163+$ iapi-mark-type [name=term typ=itype]
13284+$ iapi-mark-type [name=term typ=itype]
@@ -12236,6 +13357,9 @@
12236 ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
13357 ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
12237 ?~ prepared [%| 'API path analysis needs the prepared prelude']
13358 ?~ prepared [%| 'API path analysis needs the prepared prelude']
12238 =/ public=ifile iface.u.prepared
13359 =/ public=ifile iface.u.prepared
13360+ :: The analysis below would call a derived-name clash unsupported.
13361+ =/ clash=(unit idiag) (api-derived-clash p.parsed values.u.prepared)
13362+ ?^ clash [%| (show-duplicate-fields file src u.clash)]
12239 =/ prelude=(unit ifile) `iface.u.prepared
13363 =/ prelude=(unit ifile) `iface.u.prepared
12240 =/ deps=jimports-result
13364 =/ deps=jimports-result
12241 (resolve-jibb-imports imports.p.parsed externals marks modules ~[file] values.u.prepared molds.u.prepared ~ prelude)
13365 (resolve-jibb-imports imports.p.parsed externals marks modules ~[file] values.u.prepared molds.u.prepared ~ prelude)
@@ -12261,6 +13385,9 @@
12261 =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
13385 =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
12262 ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
13386 ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
12263 ?~ prepared [%| 'API path evidence needs the prepared prelude']
13387 ?~ prepared [%| 'API path evidence needs the prepared prelude']
13388+ :: The analysis below would call a derived-name clash unsupported.
13389+ =/ clash=(unit idiag) (api-derived-clash p.parsed values.u.prepared)
13390+ ?^ clash [%| (show-duplicate-fields file src u.clash)]
12264 =/ public=ifile iface.u.prepared
13391 =/ public=ifile iface.u.prepared
12265 =/ deps=jimports-result
13392 =/ deps=jimports-result
12266 (resolve-jibb-imports imports.p.parsed externals marks modules ~[file] values.u.prepared molds.u.prepared ~ `public)
13393 (resolve-jibb-imports imports.p.parsed externals marks modules ~[file] values.u.prepared molds.u.prepared ~ `public)
@@ -12282,6 +13409,9 @@
12282 =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
13409 =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
12283 ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
13410 ?^ duplicate [%| (show-duplicate-fields file src u.duplicate)]
12284 ?~ prepared [%| 'API path evidence needs the prepared prelude']
13411 ?~ prepared [%| 'API path evidence needs the prepared prelude']
13412+ :: The analysis below would call a derived-name clash unsupported.
13413+ =/ clash=(unit idiag) (api-derived-clash p.parsed values.u.prepared)
13414+ ?^ clash [%| (show-duplicate-fields file src u.clash)]
12285 =/ public=ifile iface.u.prepared
13415 =/ public=ifile iface.u.prepared
12286 =/ deps=jimports-result
13416 =/ deps=jimports-result
12287 (resolve-jibb-imports imports.p.parsed externals marks modules active values.u.prepared molds.u.prepared cache `public)
13417 (resolve-jibb-imports imports.p.parsed externals marks modules active values.u.prepared molds.u.prepared cache `public)
@@ -12621,38 +13751,54 @@
12621++ api-poke-interface
13751++ api-poke-interface
12622 |= [at=path mod=module mark-externals=imark-externals prelude-values=(list term) prelude-molds=(list term) prelude=(unit ifile)]
13752 |= [at=path mod=module mark-externals=imark-externals prelude-values=(list term) prelude-molds=(list term) prelude=(unit ifile)]
12623 ^- (unit ifile)
13753 ^- (unit ifile)
13754+ =/ out=(each ifile @t)
13755+ (api-poke-interface-result at mod mark-externals prelude-values prelude-molds prelude)
13756+ ?:(?=(%& -.out) `p.out ~)
13757+::
13758+:: The same check, naming the part that stopped it. Each reason says which
13759+:: part is outside this fragment and claims no error in the module, except
13760+:: duplicate definitions, an error the full check reports first, as for
13761+:: other modules.
13762+++ api-poke-interface-result
13763+ |= [at=path mod=module mark-externals=imark-externals prelude-values=(list term) prelude-molds=(list term) prelude=(unit ifile)]
13764+ ^- (each ifile @t)
12624− ?: (lien defs.mod def-has-hole) ~
13765+ ?: (lien defs.mod def-has-hole) [%| 'API holes need unsupported inference']
12625− ?. ?=([%ui %api @ %jibb ~] at) ~
13766+ ?. ?=([%ui %api @ %jibb ~] at) [%| 'API path evidence requires /ui/api/<agent>.jibb']
12626− ?^ (duplicate-defs defs.mod) ~
13767+ ?^ (duplicate-defs defs.mod) [%| 'API has duplicate definitions']
12627− ?~ prelude ~
13768+ ?~ prelude [%| 'API poke prelude needs unsupported inference']
12628− ?. =(at.u.prelude /lib/jibb/prelude/jibb) ~
13769+ ?. =(at.u.prelude /lib/jibb/prelude/jibb) [%| 'API poke prelude needs unsupported inference']
12629 =/ poke=(unit ischeme) (find-jibb-mold %raw-poke u.prelude)
13770 =/ poke=(unit ischeme) (find-jibb-mold %raw-poke u.prelude)
12630− ?~ poke ~
13771+ ?~ poke [%| 'API poke prelude needs unsupported inference']
12631− ?. ?=(%union -.typ.u.poke) ~
13772+ ?. ?=(%union -.typ.u.poke) [%| 'API poke prelude needs unsupported inference']
12632− ?^ vars.u.poke ~
13773+ ?^ vars.u.poke [%| 'API poke prelude needs unsupported inference']
12633 =/ compatible=?
13774 =/ compatible=?
12634 %+ lien cases.typ.u.poke
13775 %+ lien cases.typ.u.poke
12635 |= c=itype
13776 |= c=itype
12636 ?=([%cell [%const [%term %tas %agent *]] [%cell [%face %agent [%atom %tas]] [%cell [%face %mark [%atom %tas]] [%face %payload [%noun ~]]]]] c)
13777 ?=([%cell [%const [%term %tas %agent *]] [%cell [%face %agent [%atom %tas]] [%cell [%face %mark [%atom %tas]] [%face %payload [%noun ~]]]]] c)
12637− ?. compatible ~
13778+ ?. compatible [%| 'API poke prelude needs unsupported inference']
12638− ?. (module-scope-valid mod(defs ~) prelude-values prelude-molds) ~
13779+ :: Definitions come before imports so that a module with more than a
12639− ?. (levy imports.mod |=(i=import ?=(%mark -.i))) ~
13780+ :: `+$ poke` is not described by its imports.
12640− =/ marks=(list term) (collect-mark-imports imports.mod)
12641− ?. ?=([@ ~] marks) ~
12642 =/ ds=(list def) defs.mod
13781 =/ ds=(list def) defs.mod
12643− ?. ?=([[%mold *] ~] ds) ~
13782+ ?. ?=([[%mold *] ~] ds) [%| 'poke-only API definitions need unsupported inference']
12644− ?. =(%poke name.i.ds) ~
13783+ ?. =(%poke name.i.ds) [%| 'poke-only API definitions need unsupported inference']
13784+ ?. (module-scope-valid mod(defs ~) prelude-values prelude-molds) [%| 'API import scope needs unsupported inference']
13785+ ?. (levy imports.mod |=(i=import ?=(%mark -.i))) [%| 'poke-only API imports need unsupported inference']
13786+ =/ marks=(list term) (collect-mark-imports imports.mod)
13787+ ?. ?=([@ ~] marks) [%| 'poke-only API mark imports need unsupported inference']
12645 =/ sh=shape shape.i.ds
13788 =/ sh=shape shape.i.ds
12646− ?. ?=([%ref *] sh) ~
13789+ ?. ?=([%ref *] sh) [%| 'API poke mold needs unsupported inference']
12647− ?. ?=([@ ~] names.sh) ~
13790+ ?. ?=([@ ~] names.sh) [%| 'API poke mold needs unsupported inference']
12648 =/ n=term i.names.sh
13791 =/ n=term i.names.sh
12649− ?. (unique-value-name n marks) ~
13792+ ?. (unique-value-name n marks) [%| 'API poke mold needs unsupported inference']
12650− ?: |((lien prelude-values |=(x=term =(n x))) (lien prelude-molds |=(x=term =(n x)))) ~
13793+ ?: |((lien prelude-values |=(x=term =(n x))) (lien prelude-molds |=(x=term =(n x)))) [%| 'API poke mold needs unsupported inference']
13794+ =/ results=@ud (lent (skim mark-externals |=(e=[mark=term result=*] =(n mark.e))))
13795+ ?: =(0 results) [%| (crip "API poke mark %{(trip n)} has no reader result")]
13796+ ?. =(1 results) [%| (crip "API poke mark %{(trip n)} has duplicate reader results")]
12651 =/ mark=(unit itype) (find-imported-mark-prelude n mark-externals marks u.prelude)
13797 =/ mark=(unit itype) (find-imported-mark-prelude n mark-externals marks u.prelude)
12652− ?~ mark ~
13798+ ?~ mark [%| 'API poke mark reader result needs unsupported inference']
12653 =/ sc=(unit ischeme) (derived-poke-command-scheme u.prelude u.mark)
13799 =/ sc=(unit ischeme) (derived-poke-command-scheme u.prelude u.mark)
12654− ?~ sc ~
13800+ ?~ sc [%| 'API poke command needs unsupported inference']
12655− `[~[[%poke u.sc]] (api-mark-exports marks marks mark-externals u.prelude) at ~[[n i.t.t.at n]] ~ ~ ~ ~]
13801+ [%& [~[[%poke u.sc]] (api-mark-exports marks marks mark-externals u.prelude) at ~[[n i.t.t.at n]] ~ ~ ~ ~]]
12656::
13802::
12657:: Source-proven ordinary helpers validate each selected /sur dependency.
13803:: Source-proven ordinary helpers validate each selected /sur dependency.
12658:: Unused or less direct cores remain unsupported by this first interface.
13804:: Unused or less direct cores remain unsupported by this first interface.
@@ -12877,30 +14023,73 @@
12877 `[u.init u.update]
14023 `[u.init u.update]
12878::
14024::
12879+$ istore-declaration [action=term defs=(list def)]
14025+$ istore-declaration [action=term defs=(list def)]
14026+:: A failure carries a diagnostic only when it is a definite error of the
14027+:: source; every other failure is unsupported and carries none.
12880++ store-declaration
14028++ store-declaration
12881 |= [mod=module prelude-values=(list term) prelude-molds=(list term)]
14029 |= [mod=module prelude-values=(list term) prelude-molds=(list term)]
12882− ^- (unit istore-declaration)
14030+ ^- (each istore-declaration (unit idiag))
12883 =/ ds=(list def) defs.mod
14031 =/ ds=(list def) defs.mod
12884 =/ pokes=(list def)
14032 =/ pokes=(list def)
12885 (skim ds |=(d=def &(?=(%mold -.d) =(%poke name.d))))
14033 (skim ds |=(d=def &(?=(%mold -.d) =(%poke name.d))))
12886− ?. ?=([* ~] pokes) ~
14034+ ?. ?=([* ~] pokes) [%| ~]
12887 =/ states=(list def)
14035 =/ states=(list def)
12888 (skim ds |=(d=def &(?=(%mold -.d) =(%state name.d))))
14036 (skim ds |=(d=def &(?=(%mold -.d) =(%state name.d))))
12889− ?. ?=([* ~] states) ~
14037+ ?. ?=([* ~] states) [%| ~]
12890 =/ poke=def i.pokes
14038 =/ poke=def i.pokes
12891 =/ state=def i.states
14039 =/ state=def i.states
12892 ?> &(?=(%mold -.poke) ?=(%mold -.state))
14040 ?> &(?=(%mold -.poke) ?=(%mold -.state))
12893− ?: ?=(%generic -.shape.state) ~
14041+ ?: ?=(%generic -.shape.state) [%| ~]
12894− ?: ?=(%generic -.shape.poke) ~
14042+ ?: ?=(%generic -.shape.poke) [%| ~]
12895 =/ action=term %poke
14043 =/ action=term %poke
12896 =/ ordinary=(list def) ds
14044 =/ ordinary=(list def) ds
12897− ?. (module-scope-valid mod prelude-values prelude-molds) ~
12898 =/ derived=(list term) ~[%state action]
14045 =/ derived=(list term) ~[%state action]
12899− ?: (lien derived |=(n=term =(n %proj))) ~
14046+ ?: (lien derived reserved-name) [%| ~]
12900 =/ outer=(list term)
14047 =/ outer=(list term)
12901 (weld prelude-values (weld (global-value-names ordinary) (api-import-faces imports.mod)))
14048 (weld prelude-values (weld (global-value-names ordinary) (api-import-faces imports.mod)))
14049+ =/ clashes=(list term)
12902− ?. (levy derived |=(n=term &((unique-value-name n derived) !(lien outer |=(x=term =(n x)))))) ~
14050+ (skip derived |=(n=term &((unique-value-name n derived) !(lien outer |=(x=term =(n x))))))
14051+ :: main's `store` is the prelude's builder when the prelude declares it and
14052+ :: nothing local takes the name. Only then do the derived names surely
14053+ :: exist, and then a clash is an error even where the scope also fails, as
14054+ :: for an import face that clashes with both a derived name and its mold.
14055+ =/ builder=?
14056+ ?& (lien prelude-values |=(x=term =(x %store)))
14057+ !(lien (global-value-names ds) |=(x=term =(x %store)))
14058+ !(lien (import-binding-names imports.mod) |=(x=term =(x %store)))
14059+ ==
14060+ ?: &(?=(^ clashes) builder (lien outer |=(x=term =(x i.clashes))))
14061+ =/ from=span ?:(=(%state i.clashes) at.state at.poke)
14062+ =/ derived=[at=span note=tape] [from "`{(trip i.clashes)}` is derived from this mold"]
14063+ [%| `(derived-name-clash "store" i.clashes ~[derived] mod)]
14064+ ?. (module-scope-valid mod prelude-values prelude-molds) [%| ~]
14065+ ?^ clashes [%| ~]
12903− `[action ordinary]
14066+ [%& [action ordinary]]
14067+::
14068+:: A store or API exports names derived from its declarations, and a
14069+:: clashing derived name is an error (grammar, Modules). Show where the name
14070+:: is derived and the definition, import face or other derived name it
14071+:: clashes with; a prelude name has no site in the module.
14072+++ derived-name-clash
14073+ |= [kind=tape n=term derived=(list [at=span note=tape]) mod=module]
14074+ ^- idiag
14075+ =/ values=(list span)
14076+ (murn defs.mod |=(d=def ?.(&(?=(%value -.d) =(n name.d)) ~ `at.d)))
14077+ =/ faces=(list span)
14078+ %+ murn imports.mod
14079+ |= i=import
14080+ ?- -.i
14081+ %mark ~
14082+ %sur ?.(=(n name.i) ~ `at.i)
14083+ %jibb ?.(=(n face.i) ~ `at.i)
14084+ ==
14085+ =/ head=tape "{kind} derived name `{(trip n)}` clashes with"
14086+ ?^ values
14087+ ["{head} a definition" (weld derived ~[[i.values "clashing definition"]])]
14088+ ?^ faces
14089+ ["{head} an import face" (weld derived ~[[i.faces "clashing import face"]])]
14090+ ?: ?=([* * *] derived)
14091+ ["{head} another derived name" derived]
14092+ ["{head} a prelude name" derived]
12904::
14093::
12905++ program-empty-null
14094++ program-empty-null
12906 |= e=expr
14095 |= e=expr
@@ -12932,21 +14121,6 @@
12932 %body ?~(defs.e $(e final.e) e)
14121 %body ?~(defs.e $(e final.e) e)
12933 * e
14122 * e
12934 ==
14123 ==
12935−++ program-init-tuple-null
12936− |= d=def
12937− ^- ?
12938− ?. ?=(%value -.d) |
12939− ?. |(?=(%gate -.val.d) ?=(%gate-wide -.val.d)) |
12940− =/ body=expr
12941− ?- -.val.d
12942− %gate body.val.d
12943− %gate-wide body.val.d
12944− * !!
12945− ==
12946− =. body (program-transparent body)
12947− ?. ?=(%tuple -.body) |
12948− ?~ items.body |
12949− (program-empty-null val:(rear items.body))
12950::
14124::
12951:: Recover only the update of an already recognized direct program main.
14125:: Recover only the update of an already recognized direct program main.
12952:: Its written sample determines the message/model relationship; the canonical
14126:: Its written sample determines the message/model relationship; the canonical
@@ -12986,10 +14160,10 @@
12986 (~(put by (direct-checked-gates ds env)) update.parts update-def)
14160 (~(put by (direct-checked-gates ds env)) update.parts update-def)
12987 =/ templates=ienv
14161 =/ templates=ienv
12988 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
14162 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
12989− =/ scanned=(unit dgscan)
14163+ =/ fresh=(unit @ud)
12990− (dg-all-env-ids (weld env (weld values.u.prelude.initial templates)) 32.768 ~)
14164+ (ienv-fresh-id (weld env (weld values.u.prelude.initial templates)))
12991− ?~ scanned ~
14165+ ?~ fresh ~
12992− =. next.initial (dg-next-id ids.u.scanned 0)
14166+ =. next.initial u.fresh
12993 =/ update-state=istate (reserve-def-caps val.update-def initial)
14167 =/ update-state=istate (reserve-def-caps val.update-def initial)
12994 =/ sam=isample-result (infer-sample u.written-update env update-state)
14168 =/ sam=isample-result (infer-sample u.written-update env update-state)
12995 ?: ?=(%| -.sam) ~
14169 ?: ?=(%| -.sam) ~
@@ -13148,10 +14322,10 @@
13148 =/ checked=(map term def) (direct-checked-gates ds env)
14322 =/ checked=(map term def) (direct-checked-gates ds env)
13149 =/ templates=ienv
14323 =/ templates=ienv
13150 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
14324 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
13151− =/ scanned=(unit dgscan)
14325+ =/ fresh=(unit @ud)
13152− (dg-all-env-ids (weld env (weld values.u.prelude.initial templates)) 32.768 ~)
14326+ (ienv-fresh-id (weld env (weld values.u.prelude.initial templates)))
13153− ?~ scanned ~
14327+ ?~ fresh ~
13154− =. next.initial (dg-next-id ids.u.scanned 0)
14328+ =. next.initial u.fresh
13155 =/ subs-state=istate (reserve-def-caps val.subs-def initial)
14329 =/ subs-state=istate (reserve-def-caps val.subs-def initial)
13156 =/ sam=isample-result (infer-sample u.written-subs env subs-state)
14330 =/ sam=isample-result (infer-sample u.written-subs env subs-state)
13157 ?: ?=(%| -.sam) ~
14331 ?: ?=(%| -.sam) ~
@@ -13499,10 +14673,10 @@
13499 =/ checked=(map term def) (direct-checked-gates ds env)
14673 =/ checked=(map term def) (direct-checked-gates ds env)
13500 =/ templates=ienv
14674 =/ templates=ienv
13501 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
14675 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
13502− =/ scanned=(unit dgscan)
14676+ =/ fresh=(unit @ud)
13503− (dg-all-env-ids (weld env (weld values.u.prelude.initial templates)) 32.768 ~)
14677+ (ienv-fresh-id (weld env (weld values.u.prelude.initial templates)))
13504− ?~ scanned ~
14678+ ?~ fresh ~
13505− =. next.initial (dg-next-id ids.u.scanned 0)
14679+ =. next.initial u.fresh
13506 =/ view-state=istate (reserve-def-caps val.view-def initial)
14680 =/ view-state=istate (reserve-def-caps val.view-def initial)
13507 =/ sam=isample-result (infer-sample u.written-view env view-state)
14681 =/ sam=isample-result (infer-sample u.written-view env view-state)
13508 ?: ?=(%| -.sam) ~
14682 ?: ?=(%| -.sam) ~
@@ -13613,10 +14787,10 @@
13613 =/ checked=(map term def) (direct-checked-gates ds env)
14787 =/ checked=(map term def) (direct-checked-gates ds env)
13614 =/ templates=ienv
14788 =/ templates=ienv
13615 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
14789 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
13616− =/ scanned=(unit dgscan)
14790+ =/ fresh=(unit @ud)
13617− (dg-all-env-ids (weld env (weld values.u.prelude.initial templates)) 32.768 ~)
14791+ (ienv-fresh-id (weld env (weld values.u.prelude.initial templates)))
13618− ?~ scanned ~
14792+ ?~ fresh ~
13619− =. next.initial (dg-next-id ids.u.scanned 0)
14793+ =. next.initial u.fresh
13620 =/ view-state=istate (reserve-def-caps val.view-def initial)
14794 =/ view-state=istate (reserve-def-caps val.view-def initial)
13621 =/ sam=isample-result (infer-sample u.written-view env view-state)
14795 =/ sam=isample-result (infer-sample u.written-view env view-state)
13622 ?: ?=(%| -.sam) ~
14796 ?: ?=(%| -.sam) ~
@@ -13763,21 +14937,89 @@
13763 ?. ?=(~ (itype-vars typ.u.recovered)) ~
14937 ?. ?=(~ (itype-vars typ.u.recovered)) ~
13764 `[env.u.added grouped.resolution artifacts.u.added]
14938 `[env.u.added grouped.resolution artifacts.u.added]
13765::
14939::
13766−++ program-init-null-sample
14940+:: The model a direct program's initializer must produce. Update's written
13767− |= d=def
14941+:: two-item sample gives it when it can be read. Otherwise main's own program
13768− ^- ?
14942+:: fit does: update, view and subs are fitted together against the prelude
13769− =/ written=(unit sample) (direct-gate-sample d)
14943+:: program's sample, as main's call will fit them, with the initializer an
13770− ?~ written |
14944+:: open variable. Only the initializer's data may stay open, a replay of the
13771− ?. ?=(%bare -.u.written) |
14945+:: fit must not move, and the model must come out closed and tag-free.
13772− =/ sh=shape shape.u.written
14946+++ program-init-model
13773− ?. ?=(%const -.sh) |
14947+ |= [main=def parts=[init=term update=term view=term subs=term] ds=(list def) env=ienv program=ischeme program-def=def initial=istate]
13774− =(%null form.lit.sh)
14948+ ^- (unit itype)
13775−::
14949+ =/ relation=(unit [message=itype model=itype])
13776−:: The tuple-ending-null initializer retry above intentionally keeps its own
14950+ (program-update-relation update.parts ds env)
13777−:: boundary. A direct null-sample initializer can instead receive the closed
14951+ ?^ relation `model.u.relation
13778−:: model already established by update, view and subscriptions.
14952+ =/ args=(unit (list expr)) (program-main-args main)
14953+ ?~ args ~
14954+ =/ written=(unit sample) (direct-gate-sample program-def)
14955+ ?~ written ~
14956+ ?. ?=(%cell -.u.written) ~
14957+ ?~ items.u.written ~
14958+ =/ update=(unit ischeme) (ienv-lookup update.parts env)
14959+ =/ view=(unit ischeme) (ienv-lookup view.parts env)
14960+ =/ subs=(unit ischeme) (ienv-lookup subs.parts env)
14961+ ?~ update ~
14962+ ?~ view ~
14963+ ?~ subs ~
14964+ =/ instance=[typ=itype state=istate] (instantiate-scheme program initial)
14965+ ?. ?=(%fn -.typ.instance) ~
14966+ ?. ?=(%cell -.sample.typ.instance) ~
14967+ =/ expected-init=(unit itype)
14968+ (direct-slot-body hed.sample.typ.instance (direct-sample-name i.items.u.written))
14969+ ?~ expected-init ~
14970+ ?. ?=(%fn -.u.expected-init) ~
14971+ ?. ?=(%var -.sample.u.expected-init) ~
14972+ =/ data=@ud id.sample.u.expected-init
14973+ =/ init-var=itype [%var next.state.instance]
14974+ =/ up=[typ=itype state=istate]
14975+ (instantiate-scheme u.update state.instance(next +(next.state.instance)))
14976+ =/ vw=[typ=itype state=istate] (instantiate-scheme u.view state.up)
14977+ =/ sb=[typ=itype state=istate] (instantiate-scheme u.subs state.vw)
14978+ =/ st=istate state.sb
14979+ =/ actual=itype [%cell init-var [%cell typ.up [%cell typ.vw typ.sb]]]
14980+ =/ fit=ifit
14981+ (direct-positional-fit u.args items.u.written actual sample.typ.instance env st sub.st next.st)
14982+ ?. ?=(%ok -.fit) ~
14983+ =/ actual-final=itype (itype-normalize actual sub.fit)
14984+ =/ expected-final=itype (itype-normalize sample.typ.instance sub.fit)
14985+ =/ open=(list @ud)
14986+ (unique-type-vars (weld (itype-vars actual-final) (itype-vars expected-final)))
14987+ ?. (levy open |=(n=@ud =(data n))) ~
14988+ ?: |((itype-has-tag actual-final) (itype-has-tag expected-final)) ~
14989+ =/ replay=ifit
14990+ (direct-positional-fit u.args items.u.written actual sample.typ.instance env st sub.fit next.fit)
14991+ ?. ?=(%ok -.replay) ~
14992+ ?. &(=(sub.fit sub.replay) =(next.fit next.replay)) ~
14993+ =/ expected=itype (itype-normalize u.expected-init sub.fit)
14994+ ?. ?=(%fn -.expected) ~
14995+ ?^ (itype-vars product.expected) ~
14996+ `product.expected
14997+::
14998+:: The product of an initializer inferred ordinarily, as a whole gate with no
14999+:: expected type, for a body that context inference cannot take, such as a
15000+:: branch over a nested call's union. Its sample must fit the written one.
15001+++ program-init-ordinary
15002+ |= [init-def=def env=ienv sample=itype state=istate]
15003+ ^- iresult
15004+ ?> ?=(%value -.init-def)
15005+ =/ gate=iresult (infer-fragment val.init-def env state)
15006+ =? gate ?=(%| -.gate) (infer-recursive-gate init-def env state)
15007+ ?: ?=(%| -.gate) gate
15008+ ?. ?=(%fn -.typ.p.gate) [%| ["initializer is not a gate" ~]]
15009+ =/ fit=ifit
15010+ (itype-fit sample.typ.p.gate sample sub.state.p.gate next.state.p.gate)
15011+ ?. ?=(%ok -.fit) [%| ["initializer sample differs" ~]]
15012+ [%& product.typ.p.gate state.p.gate(sub sub.fit, next next.fit)]
15013+::
15014+:: Recover a direct program's initializer once update, view and
15015+:: subscriptions are resolved: its body is inferred against their closed
15016+:: model (+program-init-model), under its own closed written sample. This one
15017+:: path replaced a separate retry for bodies ending in null and a gate that
15018+:: took only a null sample, so any body and any closed sample check the same
15019+:: way (review question 8). The fresh ordinary main inference afterwards
15020+:: checks that all four components agree.
13779++ program-plain-init-context
15021++ program-plain-init-context
13780− |= [parts=[init=term update=term view=term subs=term] ds=(list def) resolution=iresolved initial=istate]
15022+ |= [main=def parts=[init=term update=term view=term subs=term] ds=(list def) resolution=iresolved initial=istate]
13781 ^- (unit iresolved)
15023 ^- (unit iresolved)
13782 =/ env=ienv env.resolution
15024 =/ env=ienv env.resolution
13783 ?^ (ienv-lookup %main env) ~
15025 ?^ (ienv-lookup %main env) ~
@@ -13785,15 +15027,11 @@
13785 ?~ (ienv-lookup update.parts env) ~
15027 ?~ (ienv-lookup update.parts env) ~
13786 ?~ (ienv-lookup view.parts env) ~
15028 ?~ (ienv-lookup view.parts env) ~
13787 ?~ (ienv-lookup subs.parts env) ~
15029 ?~ (ienv-lookup subs.parts env) ~
13788− =/ relation=(unit [message=itype model=itype])
13789− (program-update-relation update.parts ds env)
13790− ?~ relation ~
13791 =/ inits=(list def)
15030 =/ inits=(list def)
13792 (skim ds |=(d=def &(?=(%value -.d) =(init.parts name.d))))
15031 (skim ds |=(d=def &(?=(%value -.d) =(init.parts name.d))))
13793 ?. ?=([* ~] inits) ~
15032 ?. ?=([* ~] inits) ~
13794 =/ init-def=def i.inits
15033 =/ init-def=def i.inits
13795 ?> ?=(%value -.init-def)
15034 ?> ?=(%value -.init-def)
13796− ?. (program-init-null-sample init-def) ~
13797 =/ written=(unit sample) (direct-gate-sample init-def)
15035 =/ written=(unit sample) (direct-gate-sample init-def)
13798 ?~ written ~
15036 ?~ written ~
13799 =/ body=expr
15037 =/ body=expr
@@ -13803,141 +15041,44 @@
13803 * !!
15041 * !!
13804 ==
15042 ==
13805 ?~ prelude.initial ~
15043 ?~ prelude.initial ~
13806− ?~ (ienv-lookup %program values.u.prelude.initial) ~
15044+ =/ program=(unit ischeme) (ienv-lookup %program values.u.prelude.initial)
15045+ ?~ program ~
13807 =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude.initial)
15046 =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude.initial)
13808 ?~ heads ~
15047 ?~ heads ~
13809− ?~ (~(get by gates.u.heads) %program) ~
15048+ =/ program-def=(unit def) (~(get by gates.u.heads) %program)
15049+ ?~ program-def ~
13810 =/ checked=(map term def) (direct-checked-gates ds env)
15050 =/ checked=(map term def) (direct-checked-gates ds env)
13811 =/ templates=ienv
15051 =/ templates=ienv
13812 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
15052 (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
13813− =/ scanned=(unit dgscan)
15053+ =/ fresh=(unit @ud)
13814− (dg-all-env-ids (weld env (weld values.u.prelude.initial templates)) 32.768 ~)
15054+ (ienv-fresh-id (weld env (weld values.u.prelude.initial templates)))
13815− ?~ scanned ~
15055+ ?~ fresh ~
13816− =. next.initial (dg-next-id ids.u.scanned 0)
15056+ =. next.initial u.fresh
15057+ =/ model=(unit itype)
15058+ %: program-init-model
15059+ main parts ds env u.program u.program-def
15060+ initial(gate-defs checked, head-evidence heads)
15061+ ==
15062+ ?~ model ~
13817 =/ init-state=istate (reserve-def-caps val.init-def initial)
15063 =/ init-state=istate (reserve-def-caps val.init-def initial)
13818 =/ sam=isample-result (infer-sample u.written env init-state)
15064 =/ sam=isample-result (infer-sample u.written env init-state)
13819 ?: ?=(%| -.sam) ~
15065 ?: ?=(%| -.sam) ~
13820 ?. ?=(~ (itype-vars typ.p.sam)) ~
15066 ?. ?=(~ (itype-vars typ.p.sam)) ~
13821 ?: (itype-has-tag typ.p.sam) ~
15067 ?: (itype-has-tag typ.p.sam) ~
13822 =/ st=istate state.p.sam(gate-defs checked, head-evidence heads)
15068 =/ st=istate state.p.sam(gate-defs checked, head-evidence heads)
15069+ =/ contextual=iresult
15070+ (infer-call-context-arg body u.model env.p.sam st (span-of body))
13823 =/ inferred=iresult
15071 =/ inferred=iresult
13824− (infer-call-context-arg body model.u.relation env.p.sam st (span-of body))
15072+ ?: ?=(%& -.contextual) contextual
15073+ (program-init-ordinary init-def env typ.p.sam init-state(gate-defs checked, head-evidence heads))
13825 ?: ?=(%| -.inferred) ~
15074 ?: ?=(%| -.inferred) ~
13826 =/ product-fit=ifit
15075 =/ product-fit=ifit
13827− (itype-fit typ.p.inferred model.u.relation sub.state.p.inferred next.state.p.inferred)
15076+ (itype-fit typ.p.inferred u.model sub.state.p.inferred next.state.p.inferred)
13828 ?. ?=(%ok -.product-fit) ~
15077 ?. ?=(%ok -.product-fit) ~
13829 =/ merged-product=itype
15078 =/ merged-product=itype
13830− (itype-merge-faces typ.p.inferred model.u.relation sub.product-fit)
15079+ (itype-merge-faces typ.p.inferred u.model sub.product-fit)
13831 =/ actual-cast=itype [%fn typ.p.sam merged-product]
15080 =/ actual-cast=itype [%fn typ.p.sam merged-product]
13832− =/ closed=itype [%fn typ.p.sam model.u.relation]
15081+ =/ closed=itype [%fn typ.p.sam u.model]
13833− =/ cast=ifit
13834− (itype-fit actual-cast closed sub.product-fit next.product-fit)
13835− ?. ?=(%ok -.cast) ~
13836− =/ merged=itype (itype-merge-faces actual-cast closed sub.cast)
13837− =/ adjusted=iresult
13838− [%& merged state.p.inferred(sub sub.cast, next next.cast)]
13839− =/ added=(unit iadded-definition)
13840− (add-supported-result init-def adjusted init-state env checked artifacts.resolution)
13841− ?~ added ~
13842− =/ recovered=(unit ischeme) (ienv-lookup init.parts env.u.added)
13843− ?~ recovered ~
13844− ?. ?=(~ vars.u.recovered) ~
13845− ?. ?=(~ (itype-vars typ.u.recovered)) ~
13846− `[env.u.added grouped.resolution artifacts.u.added]
13847−::
13848−:: Recover only the initializer of an already recognized direct program main.
13849−:: The derived call is evidence for an ordinary init/main retry, never an
13850−:: interface to publish on its own. Any failure returns the original resolution.
13851−++ program-init-context
13852− |= [main=def parts=[init=term update=term view=term subs=term] ds=(list def) resolution=iresolved initial=istate]
13853− ^- (unit iresolved)
13854− =/ env=ienv env.resolution
13855− ?^ (ienv-lookup %main env) ~
13856− ?^ (ienv-lookup init.parts env) ~
13857− =/ update=(unit ischeme) (ienv-lookup update.parts env)
13858− =/ view=(unit ischeme) (ienv-lookup view.parts env)
13859− =/ subs=(unit ischeme) (ienv-lookup subs.parts env)
13860− ?~ update ~
13861− ?~ view ~
13862− ?~ subs ~
13863− =/ inits=(list def)
13864− (skim ds |=(d=def &(?=(%value -.d) =(init.parts name.d))))
13865− ?. ?=([* ~] inits) ~
13866− =/ init-def=def i.inits
13867− ?> ?=(%value -.init-def)
13868− ?. (program-init-tuple-null init-def) ~
13869− =/ args=(unit (list expr)) (program-main-args main)
13870− ?~ args ~
13871− ?~ prelude.initial ~
13872− =/ program=(unit ischeme) (ienv-lookup %program values.u.prelude.initial)
13873− ?~ program ~
13874− =/ heads=(unit igate-prelude-evidence) (direct-prelude-evidence ds prelude.initial)
13875− ?~ heads ~
13876− =/ written=(unit def) (~(get by gates.u.heads) %program)
13877− ?~ written ~
13878− =/ written-sample=(unit sample) (direct-gate-sample u.written)
13879− ?~ written-sample ~
13880− ?. ?=(%cell -.u.written-sample) ~
13881− ?~ items.u.written-sample ~
13882− =/ checked=(map term def) (direct-checked-gates ds env)
13883− =/ templates=ienv
13884− (turn molds.u.prelude.initial |=(x=[name=term template=ischeme] [name.x template.x]))
13885− =/ scanned=(unit dgscan)
13886− (dg-all-env-ids (weld env (weld values.u.prelude.initial templates)) 32.768 ~)
13887− ?~ scanned ~
13888− =. next.initial (dg-next-id ids.u.scanned 0)
13889− =/ instance=[typ=itype state=istate] (instantiate-scheme u.program initial)
13890− ?. ?=(%fn -.typ.instance) ~
13891− ?. ?=(%cell -.sample.typ.instance) ~
13892− =/ expected-init=(unit itype)
13893− (direct-slot-body hed.sample.typ.instance (direct-sample-name i.items.u.written-sample))
13894− ?~ expected-init ~
13895− ?. ?=(%fn -.u.expected-init) ~
13896− ?. ?=(%var -.sample.u.expected-init) ~
13897− =/ data=@ud id.sample.u.expected-init
13898− =/ init-var=itype [%var next.state.instance]
13899− =/ st=istate state.instance(next +(next.state.instance))
13900− =/ up=[typ=itype state=istate] (instantiate-scheme u.update st)
13901− =/ vw=[typ=itype state=istate] (instantiate-scheme u.view state.up)
13902− =/ sb=[typ=itype state=istate] (instantiate-scheme u.subs state.vw)
13903− =. st state.sb(gate-defs checked, head-evidence heads)
13904− =/ actual=itype [%cell init-var [%cell typ.up [%cell typ.vw typ.sb]]]
13905− =/ fit=ifit
13906− (direct-positional-fit u.args items.u.written-sample actual sample.typ.instance env st sub.st next.st)
13907− ?. ?=(%ok -.fit) ~
13908− =/ actual-final=itype (itype-normalize actual sub.fit)
13909− =/ expected-final=itype (itype-normalize sample.typ.instance sub.fit)
13910− =/ open=(list @ud)
13911− (unique-type-vars (weld (itype-vars actual-final) (itype-vars expected-final)))
13912− ?. (levy open |=(n=@ud =(data n))) ~
13913− ?: |((itype-has-tag actual-final) (itype-has-tag expected-final)) ~
13914− =/ replay=ifit
13915− (direct-positional-fit u.args items.u.written-sample actual sample.typ.instance env st sub.fit next.fit)
13916− ?. ?=(%ok -.replay) ~
13917− ?. &(=(sub.fit sub.replay) =(next.fit next.replay)) ~
13918− =/ expected=itype (itype-normalize u.expected-init sub.fit)
13919− ?. ?=(%fn -.expected) ~
13920− =. st st(sub sub.fit, next next.fit)
13921− =/ init-state=istate (reserve-def-caps val.init-def st)
13922− =/ inferred=iresult (infer-fragment val.init-def env init-state)
13923− =? inferred ?=(%| -.inferred) (infer-recursive-gate init-def env init-state)
13924− ?: ?=(%| -.inferred) ~
13925− ?. ?=(%fn -.typ.p.inferred) ~
13926− ?^ (itype-vars sample.typ.p.inferred) ~
13927− =/ data-fit=ifit
13928− (itype-fit sample.typ.p.inferred sample.expected sub.state.p.inferred next.state.p.inferred)
13929− ?. ?=(%ok -.data-fit) ~
13930− =/ closed=itype (itype-normalize expected sub.data-fit)
13931− ?. ?=(%fn -.closed) ~
13932− :: Resolve the ordinary tuple cast first, then check the complete gate.
13933− :: General function fit remains unchanged; only this recovered candidate
13934− :: receives the derived result context before its whole-type cast fit.
13935− =/ product-fit=ifit
13936− (itype-fit product.typ.p.inferred product.closed sub.data-fit next.data-fit)
13937− ?. ?=(%ok -.product-fit) ~
13938− =/ product=itype
13939− (itype-merge-faces product.typ.p.inferred product.closed sub.product-fit)
13940− =/ actual-cast=itype [%fn sample.typ.p.inferred product]
13941 =/ cast=ifit
15082 =/ cast=ifit
13942 (itype-fit actual-cast closed sub.product-fit next.product-fit)
15083 (itype-fit actual-cast closed sub.product-fit next.product-fit)
13943 ?. ?=(%ok -.cast) ~
15084 ?. ?=(%ok -.cast) ~
@@ -14308,12 +15449,48 @@
14308 ?: &(?=([%ui %api *] at) ?=(^ (program-main-def defs.mod)))
15449 ?: &(?=([%ui %api *] at) ?=(^ (program-main-def defs.mod)))
14309 [%| [(crip "module kind needs unsupported inference: {(spud at)}") ~]]
15450 [%| [(crip "module kind needs unsupported inference: {(spud at)}") ~]]
14310 ?: ?=([%ui %api *] at)
15451 ?: ?=([%ui %api *] at)
15452+ =/ poke=(each ifile @t)
14311− =/ iface=(unit ifile) (api-poke-interface at mod mark-externals prelude-values prelude-molds prelude)
15453+ (api-poke-interface-result at mod mark-externals prelude-values prelude-molds prelude)
15454+ ?: ?=(%& -.poke)
14312− ?^ iface
15455+ =/ iface=ifile p.poke
14313− =/ checked=ifile u.iface(source `src, graph `[(silt `(list path)`~[at]) ~ ~ modules prelude prelude-values prelude-molds externals mark-externals])
15456+ =/ checked=ifile iface(source `src, graph `[(silt `(list path)`~[at]) ~ ~ modules prelude prelude-values prelude-molds externals mark-externals])
14314 [%& [checked [[at checked] cache]]]
15457 [%& [checked [[at checked] cache]]]
15458+ :: A clashing derived name is an error wherever the checks below stop.
15459+ =/ clash=(unit idiag)
15460+ ?. ?=([%ui %api @ %jibb ~] at) ~
15461+ (api-derived-clash mod prelude-values)
15462+ ?^ clash [%| [(show-duplicate-fields at src u.clash) ~]]
15463+ :: So is a name conflict in its scope, reported as for other modules.
15464+ :: `+$ paths` and `+$ poke` are declarations, not molds (overview), and
15465+ :: a `/%` mark names a mold, so it conflicts only with another mark or
15466+ :: mold: `/% %todos` beside the request `todos` is the usual API.
15467+ =/ ordinary=(list def)
15468+ (skim defs.mod |=(d=def !&(?=(%mold -.d) |(=(%paths name.d) =(%poke name.d)))))
15469+ =/ marks=(list term) (collect-mark-imports imports.mod)
15470+ =/ mold-names=(list term)
15471+ (turn (collect-simple-molds ordinary) |=(m=[name=term body=shape] name.m))
15472+ =/ faces=(list import) (skip imports.mod |=(i=import ?=(%mark -.i)))
15473+ ?. ?& (module-scope-valid mod(defs ordinary, imports faces) prelude-values prelude-molds)
15474+ %+ levy marks
15475+ |= n=term
15476+ ?& (unique-value-name n marks)
15477+ !(lien mold-names |=(m=term =(m n)))
15478+ !(lien prelude-molds |=(m=term =(m n)))
15479+ ==
15480+ ==
15481+ [%| [(crip "module has conflicting names: {(spud at)}") ~]]
14315 ?~ prelude [%| [(crip "API module needs unsupported inference: {(spud at)}") ~]]
15482 ?~ prelude [%| [(crip "API module needs unsupported inference: {(spud at)}") ~]]
14316 =/ prepared=iprelude [u.prelude prelude-values prelude-molds]
15483 =/ prepared=iprelude [u.prelude prelude-values prelude-molds]
15484+ :: A failing Jibb import gives its own error, which may be definite, as
15485+ :: it does for other modules; the constructors below would only wrap it.
15486+ :: They resolve the same imports again, from the interfaces cached here.
15487+ =/ js=jimports-detailed-result
15488+ (resolve-jibb-imports-detailed imports.mod externals mark-externals modules active prelude-values prelude-molds cache prelude)
15489+ ?: ?=(%| -.js) [%| p.js]
15490+ :: Without `+$ paths` only the poke-only interface applies; keep its reason.
15491+ ?. (lien defs.mod |=(d=def &(?=(%mold -.d) =(%paths name.d))))
15492+ [%| [(crip "API module needs unsupported inference: {(spud at)}: {(trip p.poke)}") ~]]
15493+ :: Each constructor names the part that stopped it; keep that reason.
14317 =/ narrow=?
15494 =/ narrow=?
14318 ?. ?=([[%mark *] ~] imports.mod) |
15495 ?. ?=([[%mark *] ~] imports.mod) |
14319 ?. ?=([[%mold *] ~] defs.mod) |
15496 ?. ?=([[%mold *] ~] defs.mod) |
@@ -14321,13 +15498,13 @@
14321 !?=(%union -.shape.i.defs.mod)
15498 !?=(%union -.shape.i.defs.mod)
14322 ?: narrow
15499 ?: narrow
14323 =/ request=(each ione-request-interface @t)
15500 =/ request=(each ione-request-interface @t)
14324− (one-request-interface-graph at src externals mark-externals modules active cache `prepared)
15501+ (one-request-interface-graph at src externals mark-externals modules active cache.p.js `prepared)
14325− ?: ?=(%| -.request) [%| [(crip "API module needs unsupported inference: {(spud at)}") ~]]
15502+ ?: ?=(%| -.request) [%| [(crip "API module needs unsupported inference: {(spud at)}: {(trip p.request)}") ~]]
14326 =/ checked=ifile iface.p.request
15503 =/ checked=ifile iface.p.request
14327 [%& [checked [[at checked] dependencies.paths.support.p.request]]]
15504 [%& [checked [[at checked] dependencies.paths.support.p.request]]]
14328 =/ multi=(each [iface=ifile cache=jcache] @t)
15505 =/ multi=(each [iface=ifile cache=jcache] @t)
14329− (multi-request-interface-graph at src externals mark-externals modules active cache `prepared)
15506+ (multi-request-interface-graph at src externals mark-externals modules active cache.p.js `prepared)
14330− ?: ?=(%| -.multi) [%| [(crip "API module needs unsupported inference: {(spud at)}") ~]]
15507+ ?: ?=(%| -.multi) [%| [(crip "API module needs unsupported inference: {(spud at)}: {(trip p.multi)}") ~]]
14331 [%& [iface.p.multi [[at iface.p.multi] cache.p.multi]]]
15508 [%& [iface.p.multi [[at iface.p.multi] cache.p.multi]]]
14332 =/ main=(unit def) (program-main-def defs.mod)
15509 =/ main=(unit def) (program-main-def defs.mod)
14333 =/ main-parts=(unit [init=term update=term view=term subs=term])
15510 =/ main-parts=(unit [init=term update=term view=term subs=term])
@@ -14336,8 +15513,12 @@
14336 ?~(main ~ (page-main-parts u.main))
15513 ?~(main ~ (page-main-parts u.main))
14337 =/ store-parts=(unit [init=term update=term])
15514 =/ store-parts=(unit [init=term update=term])
14338 ?~(main ~ (store-main-parts u.main))
15515 ?~(main ~ (store-main-parts u.main))
15516+ =/ declaration=(each istore-declaration (unit idiag))
15517+ ?~(store-parts [%| ~] (store-declaration mod prelude-values prelude-molds))
15518+ =/ clash=(unit idiag) ?:(?=(%| -.declaration) p.declaration ~)
15519+ ?^ clash [%| [(show-duplicate-fields at src u.clash) ~]]
14339 =/ declared=(unit istore-declaration)
15520 =/ declared=(unit istore-declaration)
14340− ?~(store-parts ~ (store-declaration mod prelude-values prelude-molds))
15521+ ?:(?=(%| -.declaration) ~ `p.declaration)
14341 ?: &(?=(^ store-parts) ?=(~ declared))
15522 ?: &(?=(^ store-parts) ?=(~ declared))
14342 [%| [(crip "module kind or scope needs unsupported inference: {(spud at)}") ~]]
15523 [%| [(crip "module kind or scope needs unsupported inference: {(spud at)}") ~]]
14343 ?: &(?=([%ui %stores *] at) ?=(^ main) ?=(~ store-parts))
15524 ?: &(?=([%ui %stores *] at) ?=(^ main) ?=(~ store-parts))
@@ -14401,11 +15582,8 @@
14401 ?^(viewed ~ (program-plain-view-context u.main-parts ds with-keyed-view state))
15582 ?^(viewed ~ (program-plain-view-context u.main-parts ds with-keyed-view state))
14402 =/ with-view=iresolved ?~(plain-view with-keyed-view u.plain-view)
15583 =/ with-view=iresolved ?~(plain-view with-keyed-view u.plain-view)
14403 =/ initialized=(unit iresolved)
15584 =/ initialized=(unit iresolved)
14404− (program-init-context u.main u.main-parts ds with-view state)
15585+ (program-plain-init-context u.main u.main-parts ds with-view state)
14405− =/ with-initialized=iresolved ?~(initialized with-view u.initialized)
14406− =/ plain-init=(unit iresolved)
14407− ?^(initialized ~ (program-plain-init-context u.main-parts ds with-initialized state))
14408− =/ components=iresolved ?~(plain-init with-initialized u.plain-init)
15586+ =/ components=iresolved ?~(initialized with-view u.initialized)
14409 (program-main-context u.main ds components state)
15587 (program-main-context u.main ds components state)
14410 =. env env.recovered
15588 =. env env.recovered
14411 =. artifacts.resolution artifacts.recovered
15589 =. artifacts.resolution artifacts.recovered
@@ -14426,7 +15604,15 @@
14426 =/ pending=(unit [at=span msg=tape]) (module-pending-tag required env state 64)
15604 =/ pending=(unit [at=span msg=tape]) (module-pending-tag required env state 64)
14427 ?^ pending
15605 ?^ pending
14428 [%| [(show-error src [at line.beg.at.u.pending col.beg.at.u.pending msg.u.pending]) ~]]
15606 [%| [(show-error src [at line.beg.at.u.pending col.beg.at.u.pending msg.u.pending]) ~]]
15607+ :: A shadowing sample is an error, so it comes before any named value.
15608+ =/ values=(list term) (weld prelude-values (weld (api-import-faces imports.mod) vals))
15609+ =/ shadow=(unit [name=term at=span]) (module-sample-shadow required env values)
15610+ ?^ shadow
15611+ =/ msg=tape "sample `{(trip name.u.shadow)}` shadows a name already in scope"
15612+ [%| [(show-error src [at line.beg.at.u.shadow col.beg.at.u.shadow msg]) ~]]
15613+ =/ missing=(unit term) (module-missing-value required env)
15614+ =/ named=tape ?~(missing "" ": ++ {(trip u.missing)}")
14429− [%| [(crip "module definitions need unsupported inference: {(spud at)}") ~]]
15615+ [%| [(crip "module definitions need unsupported inference: {(spud at)}{named}") ~]]
14430 =/ initial=irequest-graph [(silt `(list path)`~[at]) ~ ~ modules prelude prelude-values prelude-molds externals mark-externals]
15616 =/ initial=irequest-graph [(silt `(list path)`~[at]) ~ ~ modules prelude prelude-values prelude-molds externals mark-externals]
14431 =/ graph=(unit irequest-graph) (request-graph-merge resolved.p.js initial (add 1 (lent resolved.p.js)))
15617 =/ graph=(unit irequest-graph) (request-graph-merge resolved.p.js initial (add 1 (lent resolved.p.js)))
14432 ?~ graph [%| ['module request evidence needs unsupported inference' ~]]
15618 ?~ graph [%| ['module request evidence needs unsupported inference' ~]]
@@ -14627,8 +15813,8 @@
14627 ?: ?=(%| -.parsed) (show-error src p.parsed)
15813 ?: ?=(%| -.parsed) (show-error src p.parsed)
14628 =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
15814 =/ duplicate=(unit idiag) (duplicate-defs defs.p.parsed)
14629 ?^ duplicate (duplicate-fields-report file src u.duplicate)
15815 ?^ duplicate (duplicate-fields-report file src u.duplicate)
14630− ?: (module-has-reserved-proj p.parsed)
15816+ ?: (module-has-reserved p.parsed)
14631− 'module has reserved proj name'
15817+ 'module has a reserved proj or unface name'
14632 =/ ds=(list def) defs.p.parsed
15818 =/ ds=(list def) defs.p.parsed
14633 =/ molds=imolds (collect-simple-molds ds)
15819 =/ molds=imolds (collect-simple-molds ds)
14634 =/ globals=(list term) (weld prelude-values (weld (turn jimports |=(j=[face=term interface=ifile] face.j)) (global-value-names ds)))
15820 =/ globals=(list term) (weld prelude-values (weld (turn jimports |=(j=[face=term interface=ifile] face.j)) (global-value-names ds)))
@@ -14706,7 +15892,7 @@
14706 =. head-evidence.initial heads
15892 =. head-evidence.initial heads
14707 =. initial (reserve-def-caps val.d initial)
15893 =. initial (reserve-def-caps val.d initial)
14708 =/ result=iresult
15894 =/ result=iresult
14709− ?: |(?=(%gate -.val.d) ?=(%gate-wide -.val.d))
15895+ ?: |(?=(%gate -.val.d) ?=(%gate-wide -.val.d) ?=(^ (unfaced-gate val.d env initial)))
14710 (infer-recursive-gate d env initial)
15896 (infer-recursive-gate d env initial)
14711 (infer-fragment val.d env initial)
15897 (infer-fragment val.d env initial)
14712 ?: ?=(%| -.result)
15898 ?: ?=(%| -.result)
@@ -14736,11 +15922,10 @@
14736 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)
15922 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)
14737 $(ds t.ds, lines [(crip "++ {(trip name.d)}: unresolved aura-variable inference") lines])
15923 $(ds t.ds, lines [(crip "++ {(trip name.d)}: unresolved aura-variable inference") lines])
14738 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
15924 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
14739− ?: (gth (lent vars) 26)
14740− $(ds t.ds, lines [(crip "++ {(trip name.d)}: too many variables for partial printer") lines])
14741 ?~ (width-finalize projections.state.p.result sub.state.p.result vars)
15925 ?~ (width-finalize projections.state.p.result sub.state.p.result vars)
14742 $(ds t.ds, lines [(crip "++ {(trip name.d)}: record projection elaboration needs unsupported inference") lines])
15926 $(ds t.ds, lines [(crip "++ {(trip name.d)}: record projection elaboration needs unsupported inference") lines])
15927+ =/ named=[typ=itype vars=(list @ud)] (cap-names typ vars caps.state.p.result sub.state.p.result)
14743− =/ printable=itype (canonical-itype typ vars)
15928+ =/ printable=itype (canonical-itype named)
14744 =/ line=@t (crip "++ {(trip name.d)}: {(show-itype printable ~)}{(show-atom-constraint printable)}")
15929 =/ line=@t (crip "++ {(trip name.d)}: {(show-itype printable ~)}{(show-atom-constraint printable)}")
14745 $(ds t.ds, lines [line lines])
15930 $(ds t.ds, lines [line lines])
14746:: Experimental module-owned pending-constraint generalization only.
15931:: Experimental module-owned pending-constraint generalization only.
@@ -14837,7 +16022,7 @@
14837 =/ normalized=itype (itype-normalize typ sub.state)
16022 =/ normalized=itype (itype-normalize typ sub.state)
14838 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
16023 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
14839 =/ quantified=(list @ud) (skim vars |=(n=@ud !(lien ids.u.tagged |=(b=@ud =(b n)))))
16024 =/ quantified=(list @ud) (skim vars |=(n=@ud !(lien ids.u.tagged |=(b=@ud =(b n)))))
14840− `[[normalized quantified]]
16025+ `(cap-names normalized quantified caps.state sub.state)
14841::
16026::
14842+$ dgcommit [env=ienv state=istate]
16027+$ dgcommit [env=ienv state=istate]
14843:: A branch literal must not acquire a value face through replay.
16028:: A branch literal must not acquire a value face through replay.
@@ -14929,6 +16114,8 @@
14929 ?: ?=(%| -.left) left
16114 ?: ?=(%| -.left) left
14930 =/ right=iresult (infer-fragment val.y env state.p.left)
16115 =/ right=iresult (infer-fragment val.y env state.p.left)
14931 ?: ?=(%| -.right) right
16116 ?: ?=(%| -.right) right
16117+ =/ joined=(unit [typ=itype sub=isub]) (itype-branch-join typ.p.left typ.p.right sub.state.p.right)
16118+ ?^ joined [%& typ.u.joined state.p.right(sub sub.u.joined)]
14932 ?. (dg-stable-fit typ.p.left typ.p.right sub.state.p.right)
16119 ?. (dg-stable-fit typ.p.left typ.p.right sub.state.p.right)
14933 =/ st=istate state.p.right
16120 =/ st=istate state.p.right
14934 ?. (dg-owned-arm-literal val.x typ.p.left tags.st sub.st next.state)
16121 ?. (dg-owned-arm-literal val.x typ.p.left tags.st sub.st next.state)
@@ -15173,7 +16360,6 @@
15173 ?~ env &
16360 ?~ env &
15174 =/ sc=ischeme scheme.i.env
16361 =/ sc=ischeme scheme.i.env
15175 ?: |((itype-has-hidden-recursive typ.sc) (itype-has-hidden-generic typ.sc)) |
16362 ?: |((itype-has-hidden-recursive typ.sc) (itype-has-hidden-generic typ.sc)) |
15176− ?: (gth (lent vars.sc) 26) |
15177 $(env t.env)
16363 $(env t.env)
15178:: Parse status and the transaction result come from the same source parse.
16364:: Parse status and the transaction result come from the same source parse.
15179+$ dgparse [parsed=? result=(unit dgcommit)]
16365+$ dgparse [parsed=? result=(unit dgcommit)]
@@ -15202,9 +16388,9 @@
15202 =/ free=(unit dgscan) (dg-env base ~ 32.768 ~)
16388 =/ free=(unit dgscan) (dg-env base ~ 32.768 ~)
15203 ?~ free ~
16389 ?~ free ~
15204 ?^ ids.u.free ~
16390 ?^ ids.u.free ~
15205− =/ all=(unit dgscan) (dg-all-env-ids base 32.768 ~)
16391+ =/ all=(unit @ud) (ienv-fresh-id base)
15206 ?~ all ~
16392 ?~ all ~
15207− =/ fresh=@ud (dg-next-id ids.u.all 0)
16393+ =/ fresh=@ud u.all
15208 =/ st=istate *istate
16394 =/ st=istate *istate
15209 =. st st(next fresh, defer `~, molds molds, globals globals, at at, top-molds (turn molds |=(m=[name=term body=shape] name.m)), in-mold |, jrec-fuel 256)
16395 =. st st(next fresh, defer `~, molds molds, globals globals, at at, top-molds (turn molds |=(m=[name=term body=shape] name.m)), in-mold |, jrec-fuel 256)
15210 =/ checked-molds=(each imold-types @t) (module-mold-types molds st)
16396 =/ checked-molds=(each imold-types @t) (module-mold-types molds st)
@@ -15244,33 +16430,61 @@
15244 =/ free=(unit dgscan) (dg-env all-env ~ 32.768 ~)
16430 =/ free=(unit dgscan) (dg-env all-env ~ 32.768 ~)
15245 ?~ free ~
16431 ?~ free ~
15246 ?^ ids.u.free ~
16432 ?^ ids.u.free ~
15247− =/ all=(unit dgscan) (dg-all-env-ids all-env 32.768 ~)
16433+ =/ all=(unit @ud) (ienv-fresh-id all-env)
15248 ?~ all ~
16434 ?~ all ~
15249− =/ fresh=@ud (dg-next-id ids.u.all 0)
16435+ =/ fresh=@ud u.all
15250 =/ st=istate *istate
16436 =/ st=istate *istate
15251 =. st st(next fresh, defer `~, molds local-molds, globals globals, at at, reserved-molds molds.prepared, prelude prelude, top-molds (turn local-molds |=(m=[name=term body=shape] name.m)), in-mold |, jrec-fuel 256)
16437 =. st st(next fresh, defer `~, molds local-molds, globals globals, at at, reserved-molds molds.prepared, prelude prelude, top-molds (turn local-molds |=(m=[name=term body=shape] name.m)), in-mold |, jrec-fuel 256)
15252 =/ checked-molds=(each imold-types @t) (module-mold-types local-molds st)
16438 =/ checked-molds=(each imold-types @t) (module-mold-types local-molds st)
15253 ?: ?=(%| -.checked-molds) ~
16439 ?: ?=(%| -.checked-molds) ~
15254 (dg-stage defs base base st ~ 64)
16440 (dg-stage defs base base st ~ 64)
15255::
16441::
15256−++ dg-all-env-ids
16442+:: +ienv-fresh-id: one above the largest type variable or tag ID in env
16443+::
16444+:: One pass over every ID in env's schemes, quantified or free, so a
16445+:: variable numbered from it captures none of them. A %recursive or
16446+:: %jrec type names its mold and holds no variable, so it is a leaf,
16447+:: and the pass is linear in the size of the types, with no budget.
16448+:: A scheme that still holds an unresolved tag declines.
16449+::
16450+++ ienv-fresh-id
15257− |= [env=ienv fuel=@ud ids=(list @ud)]
16451+ |= env=ienv
15258− ^- (unit dgscan)
16452+ ^- (unit @ud)
15259− ?~ env `[ids fuel]
16453+ =/ top=@ud 0
15260− ?: =(0 fuel) ~
16454+ |-
16455+ ?~ env `+(top)
15261 =/ sc=ischeme scheme.i.env
16456 =/ sc=ischeme scheme.i.env
15262 ?: (itype-has-tag typ.sc) ~
16457 ?: (itype-has-tag typ.sc) ~
15263− =/ raw=(unit dgscan) (dg-scan ~[typ.sc] ~ (dec fuel) ids)
16458+ $(env t.env, top (itype-max-id typ.sc (max top (roll (turn vars.sc var-count) max))))
15264− ?~ raw ~
16459+::
15265− =/ quant=(unit dgscan) (dg-scan-ids vars.sc ~ fuel.u.raw ids.u.raw)
16460+:: +itype-max-id: the largest variable or tag ID in t, or top, without
15266− ?~ quant ~
16461+:: the variables' names (+named-var)
15267− $(env t.env, fuel fuel.u.quant, ids ids.u.quant)
16462+::
16463+++ itype-max-id
16464+ |= [t=itype top=@ud]
16465+ ^- @ud
16466+ ?- -.t
16467+ %var (max top (var-count id.t))
16468+ %fvar (max top (var-count id.t))
16469+ %avar (max top (var-count id.t))
16470+ %rvar (max top (var-count id.t))
16471+ %nvar (max top (var-count id.t))
16472+ %rnvar (max top (var-count id.t))
16473+ %tag (max top id.t)
16474+ ?(%atom %any-atom %flag %noun %empty %const %recursive %jrec) top
16475+ %collection (itype-max-ids args.t top)
16476+ %grec (itype-max-ids args.t top)
16477+ %union (itype-max-ids args.t (itype-max-ids cases.t top))
16478+ %face $(t body.t)
16479+ %fn $(t sample.t, top $(t product.t))
16480+ %cell $(t hed.t, top $(t tal.t))
16481+ ==
15268::
16482::
15269−++ dg-next-id
16483+++ itype-max-ids
15270− |= [ids=(list @ud) largest=@ud]
16484+ |= [ts=(list itype) top=@ud]
15271 ^- @ud
16485 ^- @ud
15272− ?~ ids +(largest)
16486+ ?~ ts top
15273− $(ids t.ids, largest (max largest i.ids))
16487+ $(ts t.ts, top (itype-max-id i.ts top))
15274::
16488::
15275++ dg-eligible-ctor
16489++ dg-eligible-ctor
15276 |= [e=expr head=itype actual=itype expected=itype state=istate]
16490 |= [e=expr head=itype actual=itype expected=itype state=istate]
jibb-dev/lib/jibb/prelude.jibb+183−190
@@ -8,16 +8,16 @@
8
8
9++ head |= p=[A B]
9++ head |= p=[A B]
10 ?- p
10 ?- p
11− [a b] a
11+ [a b] a
12
12
13++ tail |= p=[A B]
13++ tail |= p=[A B]
14 ?- p
14 ?- p
15− [a b] b
15+ [a b] b
16
16
17++ not |= b=?
17++ not |= b=?
18 ?- b
18 ?- b
19− %.y %.n
19+ %.y %.n
20− %.n %.y
20+ %.n %.y
21
21
22++ eq |= args=[A A] (eq-data.internal args)
22++ eq |= args=[A A] (eq-data.internal args)
23
23
@@ -31,31 +31,29 @@
31
31
32++ fall |= args=[(unit A) A]
32++ fall |= args=[(unit A) A]
33 ?- args
33 ?- args
34− [maybe fallback]
34+ [maybe fallback]
35− ?- maybe
35+ ?- maybe
36− ~ fallback
36+ ~ fallback
37− [~ value] value
37+ [~ value] value
38
38
39++ need |= maybe=(unit A)
39++ need |= maybe=(unit A)
40 ?- maybe
40 ?- maybe
41− ~ !!
41+ ~ !!
42− [~ value] value
42+ [~ value] value
43
43
44++ weld |= args=[(list A) (list A)]
44++ weld |= args=[(list A) (list A)]
45 ?- args
45 ?- args
46− [xs ys]
47− ^- (list A)
46+ [xs ys] ^- (list A)
48− ?- xs
47+ ?- xs
49− ~ ys
48+ ~ ys
50− [item rest] [item (weld rest ys)]
49+ [item rest] [item (weld rest ys)]
51
50
52++ turn |= args=[(list A) $-(A B)]
51++ turn |= args=[(list A) $-(A B)]
53 ?- args
52 ?- args
54− [xs f]
55− ^- (list B)
53+ [xs f] ^- (list B)
56− ?- xs
54+ ?- xs
57− ~ ~
55+ ~ ~
58− [item rest] [(f item) (turn rest f)]
56+ [item rest] [(f item) (turn rest f)]
59
57
60+$ dime [p=@ta q=@]
58+$ dime [p=@ta q=@]
61
59
@@ -104,17 +102,16 @@
104+$ like |$ [A] [p=hair q=(unit [p=A q=nail])]
102+$ like |$ [A] [p=hair q=(unit [p=A q=nail])]
105
103
106++ like |= [f=$-(A B) result=(like A)]
104++ like |= [f=$-(A B) result=(like A)]
107− ++ mapped
108− ^- (unit [p=B q=nail])
105+ ++ mapped ^- (unit [p=B q=nail])
109− ?- q.result
106+ ?- q.result
110− ~ ~
107+ ~ ~
111− [~ value] `[p=(f p.value) q=q.value]
108+ [~ value] `[p=(f p.value) q=q.value]
112 ^- (like B) [p=p.result q=mapped]
109 ^- (like B) [p=p.result q=mapped]
113
110
114++ wonk |= veq=(like A)
111++ wonk |= veq=(like A)
115 ?- q.veq
112 ?- q.veq
116− ~ !!
113+ ~ !!
117− [~ product] p.product
114+ [~ product] p.product
118
115
119+$ lone |$ [A] [p=A]
116+$ lone |$ [A] [p=A]
120
117
@@ -143,214 +140,209 @@
143
140
144++ snoc |= args=[(list A) A]
141++ snoc |= args=[(list A) A]
145 ?- args
142 ?- args
146− [xs item] (weld xs [item ~])
143+ [xs item] (weld xs [item ~])
147
144
148++ flop |= xs=(list A)
145++ flop |= xs=(list A)
149 ++ reverse-into |= args=[(list A) (list A)]
146 ++ reverse-into |= args=[(list A) (list A)]
150 ?- args
147 ?- args
151− [rest acc]
148+ [rest acc]
152− ?- rest
149+ ?- rest
153− ~ acc
150+ ~ acc
154− [item more] (reverse-into more [item acc])
151+ [item more] (reverse-into more [item acc])
155 (reverse-into xs ~)
152 (reverse-into xs ~)
156
153
157−++ drop |= maybe=(unit A)
154+++ drop |= maybe=(unit A) ^- (list A)
158− ^- (list A)
159− ?- maybe
155+ ?- maybe
160− ~ ~
156+ ~ ~
161− [~ value] [value ~]
157+ [~ value] [value ~]
162
158
163++ bond |= fallback=$-(~ A)
159++ bond |= fallback=$-(~ A)
164 |= maybe=(unit A)
160 |= maybe=(unit A)
165 ?- maybe
161 ?- maybe
166− ~ (fallback ~)
162+ ~ (fallback ~)
167− [~ value] value
163+ [~ value] value
168
164
169++ bind |= args=[(unit A) $-(A B)]
165++ bind |= args=[(unit A) $-(A B)]
170 ?- args
166 ?- args
171− [maybe f] ^- (unit B)
167+ [maybe f] ^- (unit B)
172− ?- maybe
168+ ?- maybe
173− ~ ~
169+ ~ ~
174− [~ value] `(f value)
170+ [~ value] `(f value)
175
171
176++ biff |= args=[(unit A) $-(A (unit B))]
172++ biff |= args=[(unit A) $-(A (unit B))]
177 ?- args
173 ?- args
178− [maybe f] ^- (unit B)
174+ [maybe f] ^- (unit B)
179− ?- maybe
175+ ?- maybe
180− ~ ~
176+ ~ ~
181− [~ value] (f value)
177+ [~ value] (f value)
182
178
183++ both |= args=[(unit A) (unit B)]
179++ both |= args=[(unit A) (unit B)]
184 ?- args
180 ?- args
185− [first second] ^- (unit [A B])
181+ [first second] ^- (unit [A B])
186− ?- first
182+ ?- first
187− ~ ~
183+ ~ ~
188− [~ a]
184+ [~ a]
189− ?- second
185+ ?- second
190− ~ ~
186+ ~ ~
191− [~ b] `[a b]
187+ [~ b] `[a b]
192
188
193++ clap |= args=[(unit A) (unit A) $-([A A] A)]
189++ clap |= args=[(unit A) (unit A) $-([A A] A)]
194 ?- args
190 ?- args
195− [first second combine] ^- (unit A)
191+ [first second combine] ^- (unit A)
196− ?- first
192+ ?- first
197− ~ second
193+ ~ second
198− [~ a]
194+ [~ a]
199− ?- second
195+ ?- second
200− ~ first
196+ ~ first
201− [~ b] `(combine a b)
197+ [~ b] `(combine a b)
202
198
203++ hunt |= args=[$-([A A] ?) (unit A) (unit A)]
199++ hunt |= args=[$-([A A] ?) (unit A) (unit A)]
204 ?- args
200 ?- args
205− [choose first second] ^- (unit A)
201+ [choose first second] ^- (unit A)
206− ?- first
202+ ?- first
207− ~ second
203+ ~ second
208− [~ a]
204+ [~ a]
209− ?- second
205+ ?- second
210− ~ first
206+ ~ first
211− [~ b]
207+ [~ b]
212− ?- (choose a b)
208+ ?- (choose a b)
213− %.y first
209+ %.y first
214− %.n second
210+ %.n second
215
211
216++ mate |= args=[(unit A) (unit A)]
212++ mate |= args=[(unit A) (unit A)]
217 ?- args
213 ?- args
218− [first second] ^- (unit A)
214+ [first second] ^- (unit A)
219− ?- second
215+ ?- second
220− ~ first
216+ ~ first
221− [~ b]
217+ [~ b]
222− ?- first
218+ ?- first
223− ~ second
219+ ~ second
224− [~ a]
220+ [~ a]
225− ?- (eq a b)
221+ ?- (eq a b)
226− %.y first
222+ %.y first
227− %.n !!
223+ %.n !!
228
224
229++ clef |= args=[(unit A) (unit B) $-([A B] (unit C))]
225++ clef |= args=[(unit A) (unit B) $-([A B] (unit C))]
230 ?- args
226 ?- args
231− [first second combine] ^- (unit C)
227+ [first second combine] ^- (unit C)
232− ?- first
228+ ?- first
233− ~ ~
229+ ~ ~
234− [~ a]
230+ [~ a]
235− ?- second
231+ ?- second
236− ~ ~
232+ ~ ~
237− [~ b] (combine a b)
233+ [~ b] (combine a b)
238
234
239++ skim |= args=[(list A) $-(A ?)]
235++ skim |= args=[(list A) $-(A ?)]
240 ?- args
236 ?- args
241− [xs predicate] ^- (list A)
237+ [xs predicate] ^- (list A)
242− ?- xs
238+ ?- xs
243− ~ ~
239+ ~ ~
244− [item rest]
240+ [item rest]
245− ?- (predicate item)
241+ ?- (predicate item)
246− %.y [item (skim rest predicate)]
242+ %.y [item (skim rest predicate)]
247− %.n (skim rest predicate)
243+ %.n (skim rest predicate)
248
244
249++ skip |= args=[(list A) $-(A ?)]
245++ skip |= args=[(list A) $-(A ?)]
250 ?- args
246 ?- args
251− [xs predicate] ^- (list A)
247+ [xs predicate] ^- (list A)
252− ?- xs
248+ ?- xs
253− ~ ~
249+ ~ ~
254− [item rest]
250+ [item rest]
255− ?- (predicate item)
251+ ?- (predicate item)
256− %.y (skip rest predicate)
252+ %.y (skip rest predicate)
257− %.n [item (skip rest predicate)]
253+ %.n [item (skip rest predicate)]
258−
254+
259−++ levy |= args=[(list A) $-(A ?)]
255+++ levy |= args=[(list A) $-(A ?)] ^- ?
260− ^- ?
261− ?- args
256+ ?- args
262− [xs predicate]
257+ [xs predicate]
263− ?- xs
258+ ?- xs
264− ~ %.y
259+ ~ %.y
265− [item rest]
260+ [item rest]
266− ?- (predicate item)
261+ ?- (predicate item)
267− %.y (levy rest predicate)
262+ %.y (levy rest predicate)
268− %.n %.n
263+ %.n %.n
269−
264+
270−++ lien |= args=[(list A) $-(A ?)]
265+++ lien |= args=[(list A) $-(A ?)] ^- ?
271− ^- ?
272− ?- args
266+ ?- args
273− [xs predicate]
267+ [xs predicate]
274− ?- xs
268+ ?- xs
275− ~ %.n
269+ ~ %.n
276− [item rest]
270+ [item rest]
277− ?- (predicate item)
271+ ?- (predicate item)
278− %.y %.y
272+ %.y %.y
279− %.n (lien rest predicate)
273+ %.n (lien rest predicate)
280
274
281++ roll |= args=[(list A) B $-([A B] B)]
275++ roll |= args=[(list A) B $-([A B] B)]
282 ?- args
276 ?- args
283− [xs start combine]
277+ [xs start combine]
284− ?- xs
278+ ?- xs
285− ~ start
279+ ~ start
286− [item rest] (roll rest (combine item start) combine)
280+ [item rest] (roll rest (combine item start) combine)
287
281
288++ reel |= args=[(list A) B $-([A B] B)]
282++ reel |= args=[(list A) B $-([A B] B)]
289 ?- args
283 ?- args
290− [xs start combine]
284+ [xs start combine]
291− ?- xs
285+ ?- xs
292− ~ start
286+ ~ start
293− [item rest] (combine item (reel rest start combine))
287+ [item rest] (combine item (reel rest start combine))
294
288
295++ flit |= predicate=$-(A ?)
289++ flit |= predicate=$-(A ?)
296− |= value=A
290+ |= value=A ^- (unit A)
297− ^- (unit A)
298− ?- (predicate value)
291+ ?- (predicate value)
299− %.y `value
292+ %.y `value
300− %.n ~
293+ %.n ~
301
294
302++ murn |= args=[(list A) $-(A (unit B))]
295++ murn |= args=[(list A) $-(A (unit B))]
303 ?- args
296 ?- args
304− [xs f] ^- (list B)
297+ [xs f] ^- (list B)
305− ?- xs
298+ ?- xs
306− ~ ~
299+ ~ ~
307− [item rest]
300+ [item rest]
308− ?- (f item)
301+ ?- (f item)
309− ~ (murn rest f)
302+ ~ (murn rest f)
310− [~ value] [value (murn rest f)]
303+ [~ value] [value (murn rest f)]
311
304
312++ join |= args=[A (list A)]
305++ join |= args=[A (list A)]
313 ?- args
306 ?- 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)
324 ?- xs
308 ?- xs
309+ ~ ~
310+ [item rest]
311+ ?- rest
325− ~ ~
312+ ~ [item ~]
326− [item rest]
313+ [next more] [item [separator (join separator rest)]]
314+
315+++ snip |= xs=(list A) ^- (list A)
316+ ?- xs
317+ ~ ~
327− ?- rest
318+ [item rest]
319+ ?- rest
328− ~ ~
320+ ~ ~
329− [next more] [item (snip rest)]
321+ [next more] [item (snip rest)]
330
322
331++ rear |= xs=(list A)
323++ rear |= xs=(list A)
332 ?- xs
324 ?- xs
333− ~ !!
325+ ~ !!
334− [item rest]
326+ [item rest]
335− ?- rest
327+ ?- rest
336− ~ item
328+ ~ item
337− [next more] (rear rest)
329+ [next more] (rear rest)
338
330
339++ cork |= gates=[$-(A B) $-(B C)]
331++ cork |= gates=[$-(A B) $-(B C)]
340 ?- gates
332 ?- gates
341− [f g] |= x=A (g (f x))
333+ [f g] |= x=A (g (f x))
342
334
343++ corl |= gates=[$-(B C) $-(A B)]
335++ corl |= gates=[$-(B C) $-(A B)]
344 ?- gates
336 ?- gates
345− [f g] |= x=A (f (g x))
337+ [f g] |= x=A (f (g x))
346
338
347++ cury |= args=[$-([A B] C) A]
339++ cury |= args=[$-([A B] C) A]
348 ?- args
340 ?- args
349− [f a] |= b=B (f a b)
341+ [f a] |= b=B (f a b)
350
342
351++ curr |= args=[$-([A B] C) B]
343++ curr |= args=[$-([A B] C) B]
352 ?- args
344 ?- args
353− [f b] |= a=A (f a b)
345+ [f b] |= a=A (f a b)
354
346
355+$ cmd |$ [M]
347+$ cmd |$ [M]
356 [%poke p=raw-poke reply=$-((unit @t) M)]
348 [%poke p=raw-poke reply=$-((unit @t) M)]
@@ -373,29 +365,27 @@
373 [%url reply=$-(path M)]
365 [%url reply=$-(path M)]
374
366
375:: Count a finite list with the source-backed addition gate.
367:: Count a finite list with the source-backed addition gate.
376−++ lent |= xs=(list A)
368+++ lent |= xs=(list A) ^- @ud
377− ^- @ud
378− ?- xs
369+ ?- xs
379− ~ 0
370+ ~ 0
380− [item rest] (add 1 (lent rest))
371+ [item rest] (add 1 (lent rest))
381
372
382++ lth |= args=[A A]
373++ lth |= args=[A A]
383 ?- args
374 ?- args
384− [x y] (gth y x)
375+ [x y] (gth y x)
385
376
386++ gte |= args=[A A]
377++ gte |= args=[A A]
387 ?- args
378 ?- args
388− [x y] (not (gth y x))
379+ [x y] (not (gth y x))
389
380
390++ lte |= args=[A A]
381++ lte |= args=[A A]
391 ?- args
382 ?- args
392− [x y] (not (gth x y))
383+ [x y] (not (gth x y))
393
384
394−++ zing |= xss=(list (list A))
385+++ zing |= xss=(list (list A)) ^- (list A)
395− ^- (list A)
396− ?- xss
386+ ?- xss
397− ~ ~
387+ ~ ~
398− [xs rest] (weld xs (zing rest))
388+ [xs rest] (weld xs (zing rest))
399
389
400++ lead |= first=A |= second=B [first second]
390++ lead |= first=A |= second=B [first second]
401++ late |= second=B |= first=A [first second]
391++ late |= second=B |= first=A [first second]
@@ -528,20 +518,23 @@
528 font=(unit qath)
518 font=(unit qath)
529 dark=(unit [tones=[normal=@t background=@t accent=@t danger=@t muted=@t]])
519 dark=(unit [tones=[normal=@t background=@t accent=@t danger=@t muted=@t]])
530
520
531−+$ program |$ [D X M]
521++$ program |$ [Data Model Msg]
532− [init=$-(D X) update=$-([M X] [X (list (cmd M))]) view=$-(X (element M)) subs=$-(X (list (sub M)))]
522+ [ init=$-(Data Model)
523+ update=$-([Msg Model] [Model (list (cmd Msg))])
524+ view=$-(Model (element Msg))
525+ subs=$-(Model (list (sub Msg)))
533
526
534−++ program |= [init=$-(D X) update=$-([M X] [X (list (cmd M))]) view=$-(X (element M)) subs=$-(X (list (sub M)))]
527+++ program |= [init=$-(Data Model) update=$-([Msg Model] [Model (list (cmd Msg))]) view=$-(Model (element Msg)) subs=$-(Model (list (sub Msg)))]
535− ^- (program D X M) [init update view subs]
528+ ^- (program Data Model Msg) [init update view subs]
536
529
537−++ island |= [p=(program D X M) data=D]
530+++ island |= [p=(program Data Model Msg) data=Data]
538 ^- (element !!) [%island [p data]]
531 ^- (element !!) [%island [p data]]
539
532
540−+$ page |$ [R D]
533++$ page |$ [Params Data]
541− [load=$-(R (ask D)) view=$-(D (element !!))]
534+ [load=$-(Params (ask Data)) view=$-(Data (element !!))]
542
535
543−++ page |= [load=$-(R (ask D)) view=$-(D (element !!))]
536+++ page |= [load=$-(Params (ask Data)) view=$-(Data (element !!))]
544− ^- (page R D) [load view]
537+ ^- (page Params Data) [load view]
545
538
546+$ store |$ [S] [init=S update=*]
539+$ store |$ [S] [init=S update=*]
547
540
my-app/desk.docket-0+1−1
@@ -3,6 +3,6 @@
3 color+0x17.734f
3 color+0x17.734f
4 version+[0 1 0]
4 version+[0 1 0]
5 website+''
5 website+''
6− license+''
6+ license+'MIT'
7 site+/apps/my-app
7 site+/apps/my-app
8==
8==
my-app/ui/basket.jibb+6−6
@@ -12,15 +12,15 @@
12 [%acked err=(unit @t)]
12 [%acked err=(unit @t)]
13
13
14++ init |= ~
14++ init |= ~
15− [[~ %.n] ""]
15+ [cart=[items=~ open=%.n] note=""]
16
16
17++ update |= [=msg m=model]
17++ update |= [=msg m=model]
18 ?- msg
18 ?- msg
19− [%noted t] [m(note=t) ~]
19+ [%noted t] [m(note=t) ~]
20− %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
20+ %add [m(note="") ~[(poke.cart [%add note.m] |=%acked)]]
21− %toggle [m ~[(poke.cart %toggle |=%acked)]]
21+ %toggle [m ~[(poke.cart %toggle |=%acked)]]
22− [%got c] [m(cart=c) ~]
22+ [%got c] [m(cart=c) ~]
23− [%acked err] [m ~]
23+ [%acked err] [m ~]
24
24
25++ subs |= m=model
25++ subs |= m=model
26 ~[[%watch (state.cart |=%got)]]
26 ~[[%watch (state.cart |=%got)]]
my-app/ui/stores/cart.jibb+3−3
@@ -5,8 +5,8 @@
5 %toggle
5 %toggle
6
6
7++ main (store init update)
7++ main (store init update)
8−++ init ^- state [~ %.n]
8+++ init ^- state [items=~ open=%.n]
9++ update |= [a=poke s=state]
9++ update |= [a=poke s=state]
10 ?- a
10 ?- a
11− [%add item] s(items=[item items.s])
11+ [%add item] s(items=[item items.s])
12− %toggle s(open=(not open.s))
12+ %toggle s(open=(not open.s))
my-app/ui/todo-list.jibb+9−9
@@ -11,18 +11,18 @@
11 [%acked err=(unit @t)]
11 [%acked err=(unit @t)]
12
12
13++ init |= ts=(list item.todo)
13++ init |= ts=(list item.todo)
14− [ts "" ~]
14+ [todos=ts draft="" error=~]
15
15
16++ update |= [=msg m=model]
16++ update |= [=msg m=model]
17 ?- msg
17 ?- msg
18− [%typed t]
18+ [%typed t]
19− ?- (gth (lent (tuba (trip t))) 80)
19+ ?- (gth (lent (tuba (trip t))) 80)
20− %.y [m(draft=t error=`"Too long") ~]
20+ %.y [m(draft=t error=`"Too long") ~]
21− %.n [m(draft=t error=~) ~]
21+ %.n [m(draft=t error=~) ~]
22− %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
22+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
23− [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
23+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
24− [%got ts] [m(todos=ts) ~]
24+ [%got ts] [m(todos=ts) ~]
25− [%acked err] [m(error=err) ~]
25+ [%acked err] [m(error=err) ~]
26
26
27++ subs |= m=model
27++ subs |= m=model
28 ~[[%watch (todos.todo |=%got)]]
28 ~[[%watch (todos.todo |=%got)]]
tests/clay-fixtures/expected.txt → tests/clay-fixtures/build-expected.txtrenamed

The content is the same.

my-app/mar/label.hoon → tests/clay-fixtures/desk/mar/label.hoonrenamed−1
@@ -1,4 +1,3 @@
1−:: Fixture for the Hoon mark importer; not supplied by the design doc.
2|_ a=@t
1|_ a=@t
3++ grab |% ++ noun @t --
2++ grab |% ++ noun @t --
4++ grow |% ++ noun a --
3++ grow |% ++ noun a --
my-app/sur/import-fixture.hoon → tests/clay-fixtures/desk/sur/import-fixture.hoonrenamed

The content is the same.

tests/clay-fixtures/desk/sur/mop-tlon-probe.hoonnew file+1
@@ -0,0 +1 @@
1+../../../golden/types-import-tlon-notes/sur/notes.txt
tests/clay-fixtures/ford-import.txt+2−2
@@ -1,8 +1,8 @@
1=/ m (strand ,vase)
1=/ m (strand ,vase)
2;< =bowl:spider bind:m get-bowl
2;< =bowl:spider bind:m get-bowl
3=/ now=@da now.bowl
3=/ now=@da now.bowl
4−=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/sur/import-fixture/hoon)
4+=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/sur/import-fixture/hoon)
5−=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/lib/jibb-import/hoon)
5+=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/lib/jibb-import/hoon)
6=/ cor=type -.src
6=/ cor=type -.src
7=/ typ=type (~(play ut cor) (ream '*sample'))
7=/ typ=type (~(play ut cor) (ream '*sample'))
8=/ read-gate=vase (slap reader (ream 'read-mold-in'))
8=/ read-gate=vase (slap reader (ream 'read-mold-in'))
tests/clay-fixtures/ford-nested-union-bridge.txt+4−4
@@ -1,10 +1,10 @@
1=/ m (strand ,vase)
1=/ m (strand ,vase)
2;< =bowl:spider bind:m get-bowl
2;< =bowl:spider bind:m get-bowl
3=/ now=@da now.bowl
3=/ now=@da now.bowl
4−=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/sur/import-fixture/hoon)
4+=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/sur/import-fixture/hoon)
5−=/ blog=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/sur/blog/hoon)
5+=/ blog=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/sur/blog/hoon)
6−=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/lib/jibb-import/hoon)
6+=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/lib/jibb-import/hoon)
7−=/ jibb=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/lib/jibb/hoon)
7+=/ jibb=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/lib/jibb/hoon)
8=/ read-gate=vase (slap reader (ream 'read-named'))
8=/ read-gate=vase (slap reader (ream 'read-named'))
9=/ result=vase (slym read-gate [%import-fixture %nested -.src])
9=/ result=vase (slym read-gate [%import-fixture %nested -.src])
10=/ sample-result=vase (slym read-gate [%import-fixture %sample -.src])
10=/ sample-result=vase (slym read-gate [%import-fixture %sample -.src])
tests/clay-fixtures/ford-nested-union.txt+2−2
@@ -1,8 +1,8 @@
1=/ m (strand ,vase)
1=/ m (strand ,vase)
2;< =bowl:spider bind:m get-bowl
2;< =bowl:spider bind:m get-bowl
3=/ now=@da now.bowl
3=/ now=@da now.bowl
4−=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/sur/import-fixture/hoon)
4+=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/sur/import-fixture/hoon)
5−=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/lib/jibb-import/hoon)
5+=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/lib/jibb-import/hoon)
6=/ read-gate=vase (slap reader (ream 'read-named'))
6=/ read-gate=vase (slap reader (ream 'read-named'))
7=/ got=vase (slym read-gate [%import-fixture %nested -.src])
7=/ got=vase (slym read-gate [%import-fixture %nested -.src])
8=/ show-gate=vase (slap reader (ream 'show-result'))
8=/ show-gate=vase (slap reader (ream 'show-result'))
tests/clay-fixtures/ford-recursive.txt+2−2
@@ -1,8 +1,8 @@
1=/ m (strand ,vase)
1=/ m (strand ,vase)
2;< =bowl:spider bind:m get-bowl
2;< =bowl:spider bind:m get-bowl
3=/ now=@da now.bowl
3=/ now=@da now.bowl
4−=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/sur/import-fixture/hoon)
4+=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/sur/import-fixture/hoon)
5−=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/lib/jibb-import/hoon)
5+=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/lib/jibb-import/hoon)
6=/ read-gate=vase (slap reader (ream 'read-named'))
6=/ read-gate=vase (slap reader (ream 'read-named'))
7=/ got=vase (slym read-gate [%import-fixture %recursive -.src])
7=/ got=vase (slym read-gate [%import-fixture %recursive -.src])
8=/ show-gate=vase (slap reader (ream 'show-result'))
8=/ show-gate=vase (slap reader (ream 'show-result'))
tests/clay-fixtures/ford.txt+1−1
@@ -1,7 +1,7 @@
1=/ m (strand ,vase)
1=/ m (strand ,vase)
2;< =bowl:spider bind:m get-bowl
2;< =bowl:spider bind:m get-bowl
3=/ now=@da now.bowl
3=/ now=@da now.bowl
4−=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/sur/import-fixture/hoon)
4+=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/sur/import-fixture/hoon)
5=/ cor=type -.src
5=/ cor=type -.src
6?. ?=([%core *] cor) (pure:m !>('not a core'))
6?. ?=([%core *] cor) (pure:m !>('not a core'))
7=/ subject=type q.q.cor
7=/ subject=type q.q.cor
tests/clay-fixtures/mark-bridge.txt+3−3
@@ -1,9 +1,9 @@
1=/ m (strand ,vase)
1=/ m (strand ,vase)
2;< =bowl:spider bind:m get-bowl
2;< =bowl:spider bind:m get-bowl
3=/ now=@da now.bowl
3=/ now=@da now.bowl
4−=/ mark=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/mar/label/hoon)
4+=/ mark=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/mar/label/hoon)
5−=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/lib/jibb-import/hoon)
5+=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/lib/jibb-import/hoon)
6−=/ jibb=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/lib/jibb/hoon)
6+=/ jibb=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/lib/jibb/hoon)
7=/ read-gate=vase (slap reader (ream 'read-mark'))
7=/ read-gate=vase (slap reader (ream 'read-mark'))
8=/ label-result=vase (slym read-gate [%label -.mark])
8=/ label-result=vase (slym read-gate [%label -.mark])
9=/ check-gate=vase (slap jibb (ream 'golden-types-with-marks'))
9=/ check-gate=vase (slap jibb (ream 'golden-types-with-marks'))
tests/clay-fixtures/tlon-mop.txt+2−2
@@ -1,8 +1,8 @@
1=/ m (strand ,vase)
1=/ m (strand ,vase)
2;< =bowl:spider bind:m get-bowl
2;< =bowl:spider bind:m get-bowl
3=/ now=@da now.bowl
3=/ now=@da now.bowl
4−=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/sur/mop-tlon-probe/hoon)
4+=/ src=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/sur/mop-tlon-probe/hoon)
5−=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/my-app/[(scot %da now)]/lib/jibb-import/hoon)
5+=/ reader=vase .^(vase %ca /[(scot %p our.bowl)]/jibb-fixtures/[(scot %da now)]/lib/jibb-import/hoon)
6=/ read-gate=vase (slap reader (ream 'read-named'))
6=/ read-gate=vase (slap reader (ream 'read-named'))
7=/ result=vase (slym read-gate [%notes %log -.src])
7=/ result=vase (slym read-gate [%notes %log -.src])
8=/ recursive=vase (slym read-gate [%notes %import-node -.src])
8=/ recursive=vase (slym read-gate [%notes %import-node -.src])
tests/golden/doc-core-02-update/about.txt+1−1
@@ -1,3 +1,3 @@
1source: Core language tab, section "Example", code block 2 of the tab
1source: 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
3expect: parses
3expect: parses
tests/golden/doc-core-02-update/source.jibb+8−8
@@ -1,10 +1,10 @@
1++ update |= [=msg m=model]
1++ update |= [=msg m=model]
2 ?- msg
2 ?- msg
3− [%typed t]
3+ [%typed t]
4− ?- (gth (lent (tuba (trip t))) 80)
4+ ?- (gth (lent (tuba (trip t))) 80)
5− %.y [m(draft=t error=`"Too long") ~]
5+ %.y [m(draft=t error=`"Too long") ~]
6− %.n [m(draft=t error=~) ~]
6+ %.n [m(draft=t error=~) ~]
7− %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
7+ %submit [m(draft="") ~[(poke.todo [%add draft.m] |=%acked)]]
8− [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
8+ [%toggled id] [m ~[(poke.todo [%toggle id] |=%acked)]]
9− [%got ts] [m(todos=ts) ~]
9+ [%got ts] [m(todos=ts) ~]
10− [%acked err] [m(error=err) ~]
10+ [%acked err] [m(error=err) ~]
tests/golden/doc-core-02-update/tokens.txt+120−122
@@ -11,126 +11,124 @@
112:3 INDENT
112:3 INDENT
122:3 glyph ?-
122:3 glyph ?-
132:6 name msg
132:6 name msg
14−3:5 INDENT
14+3:3 NEWLINE
15−3:5 glyph [
15+3:3 glyph [
16−3:6 tight lit %typed
16+3:4 tight lit %typed
17−3:13 name t
17+3:11 name t
18−3:14 tight glyph ]
18+3:12 tight glyph ]
19−4:7 INDENT
19+4:5 INDENT
20−4:7 glyph ?-
20+4:5 glyph ?-
21−4:10 glyph (
21+4:8 glyph (
22−4:11 tight name gth
22+4:9 tight name gth
23−4:15 glyph (
23+4:13 glyph (
24−4:16 tight name lent
24+4:14 tight name lent
25−4:21 glyph (
25+4:19 glyph (
26−4:22 tight name tuba
26+4:20 tight name tuba
27−4:27 glyph (
27+4:25 glyph (
28−4:28 tight name trip
28+4:26 tight name trip
29−4:33 name t
29+4:31 name t
30+4:32 tight glyph )
31+4:33 tight glyph )
304:34 tight glyph )
324:34 tight glyph )
31−4:35 tight glyph )
32−4:36 tight glyph )
33−4:38 lit 80
33+4:36 lit 80
34−4:40 tight glyph )
34+4:38 tight glyph )
35−5:9 INDENT
35+5:5 NEWLINE
36−5:9 lit %.y
36+5:5 lit %.y
37−5:14 glyph [
37+5:10 glyph [
38−5:15 tight name m
38+5:11 tight name m
39−5:16 tight glyph (
39+5:12 tight glyph (
40−5:17 tight name draft
40+5:13 tight name draft
41−5:22 tight glyph =
41+5:18 tight glyph =
42−5:23 tight name t
42+5:19 tight name t
43−5:25 name error
43+5:21 name error
44−5:30 tight glyph =
44+5:26 tight glyph =
45−5:31 tight glyph `
45+5:27 tight glyph `
46−5:32 tight str "Too long"
46+5:28 tight str "Too long"
47−5:42 tight glyph )
47+5:38 tight glyph )
48−5:44 lit ~
48+5:40 lit ~
49−5:45 tight glyph ]
49+5:41 tight glyph ]
50−6:9 NEWLINE
50+6:5 NEWLINE
51−6:9 lit %.n
51+6:5 lit %.n
52−6:14 glyph [
52+6:10 glyph [
53−6:15 tight name m
53+6:11 tight name m
54−6:16 tight glyph (
54+6:12 tight glyph (
55−6:17 tight name draft
55+6:13 tight name draft
56−6:22 tight glyph =
56+6:18 tight glyph =
57−6:23 tight name t
57+6:19 tight name t
58−6:25 name error
58+6:21 name error
59−6:30 tight glyph =
59+6:26 tight glyph =
60−6:31 tight lit ~
60+6:27 tight lit ~
61−6:32 tight glyph )
61+6:28 tight glyph )
62−6:34 lit ~
62+6:30 lit ~
63−6:35 tight glyph ]
63+6:31 tight glyph ]
64−7:5 DEDENT
64+7:3 DEDENT
65−7:5 DEDENT
66−7:5 NEWLINE
65+7:3 NEWLINE
67−7:5 lit %submit
66+7:3 lit %submit
68−7:20 glyph [
67+7:18 glyph [
69−7:21 tight name m
68+7:19 tight name m
70−7:22 tight glyph (
69+7:20 tight glyph (
71−7:23 tight name draft
70+7:21 tight name draft
72−7:28 tight glyph =
71+7:26 tight glyph =
73−7:29 tight str ""
72+7:27 tight str ""
74−7:31 tight glyph )
73+7:29 tight glyph )
75−7:33 glyph ~[
74+7:31 glyph ~[
76−7:35 tight glyph (
75+7:33 tight glyph (
77−7:36 tight wing poke.todo
76+7:34 tight wing poke.todo
78−7:46 glyph [
77+7:44 glyph [
79−7:47 tight lit %add
78+7:45 tight lit %add
80−7:52 wing draft.m
79+7:50 wing draft.m
81−7:59 tight glyph ]
80+7:57 tight glyph ]
81+7:59 glyph |=
82+7:61 tight lit %acked
82−7:61 glyph |=
83+7:67 tight glyph )
83−7:63 tight lit %acked
84+7:68 tight glyph ]
84−7:69 tight glyph )
85+7:69 tight glyph ]
85−7:70 tight glyph ]
86−7:71 tight glyph ]
87−8:5 NEWLINE
86+8:3 NEWLINE
88−8:5 glyph [
87+8:3 glyph [
89−8:6 tight lit %toggled
88+8:4 tight lit %toggled
90−8:15 name id
89+8:13 name id
91−8:17 tight glyph ]
90+8:15 tight glyph ]
92−8:20 glyph [
91+8:18 glyph [
93−8:21 tight name m
92+8:19 tight name m
94−8:23 glyph ~[
93+8:21 glyph ~[
95−8:25 tight glyph (
94+8:23 tight glyph (
96−8:26 tight wing poke.todo
95+8:24 tight wing poke.todo
97−8:36 glyph [
96+8:34 glyph [
98−8:37 tight lit %toggle
97+8:35 tight lit %toggle
99−8:45 name id
98+8:43 name id
100−8:47 tight glyph ]
99+8:45 tight glyph ]
101−8:49 glyph |=
100+8:47 glyph |=
102−8:51 tight lit %acked
101+8:49 tight lit %acked
103−8:57 tight glyph )
102+8:55 tight glyph )
104−8:58 tight glyph ]
103+8:56 tight glyph ]
105−8:59 tight glyph ]
104+8:57 tight glyph ]
106−9:5 NEWLINE
105+9:3 NEWLINE
107−9:5 glyph [
106+9:3 glyph [
108−9:6 tight lit %got
107+9:4 tight lit %got
109−9:11 name ts
108+9:9 name ts
110−9:13 tight glyph ]
109+9:11 tight glyph ]
111−9:20 glyph [
110+9:18 glyph [
112−9:21 tight name m
111+9:19 tight name m
113−9:22 tight glyph (
112+9:20 tight glyph (
114−9:23 tight name todos
113+9:21 tight name todos
115−9:28 tight glyph =
114+9:26 tight glyph =
116−9:29 tight name ts
115+9:27 tight name ts
117−9:31 tight glyph )
116+9:29 tight glyph )
118−9:33 lit ~
117+9:31 lit ~
119−9:34 tight glyph ]
118+9:32 tight glyph ]
120−10:5 NEWLINE
119+10:3 NEWLINE
121−10:5 glyph [
120+10:3 glyph [
122−10:6 tight lit %acked
121+10:4 tight lit %acked
123−10:13 name err
122+10:11 name err
124−10:16 tight glyph ]
123+10:14 tight glyph ]
125−10:20 glyph [
124+10:18 glyph [
126−10:21 tight name m
125+10:19 tight name m
127−10:22 tight glyph (
126+10:20 tight glyph (
128−10:23 tight name error
127+10:21 tight name error
129−10:28 tight glyph =
128+10:26 tight glyph =
130−10:29 tight name err
129+10:27 tight name err
131−10:32 tight glyph )
130+10:30 tight glyph )
132−10:34 lit ~
131+10:32 lit ~
133−10:35 tight glyph ]
132+10:33 tight glyph ]
134−10:36 DEDENT
133+10:34 DEDENT
135−10:36 DEDENT
136−10:36 NEWLINE
134+10:34 NEWLINE
tests/golden/doc-core-02-update/tree.txt+64−64
@@ -7,67 +7,67 @@
7 (body 2:3
7 (body 2:3
8 (branch 2:3
8 (branch 2:3
9 (wing 2:6 msg)
9 (wing 2:6 msg)
10− (arm 3:5
10+ (arm 3:3
11− (cell 3:5 (lit 3:6 %typed) (bind 3:13 t))
11+ (cell 3:3 (lit 3:4 %typed) (bind 3:11 t))
12− (body 4:7
12+ (body 4:5
13− (branch 4:7
13+ (branch 4:5
14− (group 4:10
14+ (group 4:8
15− (call 4:11
15+ (call 4:9
16− (wing 4:11 gth)
16+ (wing 4:9 gth)
17− (group 4:15
17+ (group 4:13
18− (call 4:16
18+ (call 4:14
19− (wing 4:16 lent)
19+ (wing 4:14 lent)
20− (group 4:21
20+ (group 4:19
21− (call 4:22
21+ (call 4:20
22− (wing 4:22 tuba)
22+ (wing 4:20 tuba)
23− (group 4:27
23+ (group 4:25
24− (call 4:28 (wing 4:28 trip) (wing 4:33 t)))))))
24+ (call 4:26 (wing 4:26 trip) (wing 4:31 t)))))))
25− (lit 4:38 80)))
25+ (lit 4:36 80)))
26− (arm 5:9
26+ (arm 5:5
27− (lit 5:9 %.y)
27+ (lit 5:5 %.y)
28− (tuple 5:14
28+ (tuple 5:10
29− (change 5:15 m
29+ (change 5:11 m
30− (edit 5:17 draft (wing 5:23 t))
30+ (edit 5:13 draft (wing 5:19 t))
31− (edit 5:25 error
31+ (edit 5:21 error
32− (unit 5:31 (str 5:32 "Too long"))))
32+ (unit 5:27 (str 5:28 "Too long"))))
33− (lit 5:44 ~)))
33+ (lit 5:40 ~)))
34− (arm 6:9
34+ (arm 6:5
35− (lit 6:9 %.n)
35+ (lit 6:5 %.n)
36− (tuple 6:14
36+ (tuple 6:10
37− (change 6:15 m
37+ (change 6:11 m
38− (edit 6:17 draft (wing 6:23 t))
38+ (edit 6:13 draft (wing 6:19 t))
39− (edit 6:25 error (lit 6:31 ~)))
39+ (edit 6:21 error (lit 6:27 ~)))
40− (lit 6:34 ~))))))
40+ (lit 6:30 ~))))))
41− (arm 7:5
41+ (arm 7:3
42− (lit 7:5 %submit)
42+ (lit 7:3 %submit)
43− (tuple 7:20
43+ (tuple 7:18
44− (change 7:21 m
44+ (change 7:19 m
45− (edit 7:23 draft (str 7:29 "")))
45+ (edit 7:21 draft (str 7:27 "")))
46− (list 7:33
46+ (list 7:31
47− (group 7:35
47+ (group 7:33
48− (call 7:36
48+ (call 7:34
49− (wing 7:36 poke.todo)
49+ (wing 7:34 poke.todo)
50− (tuple 7:46 (lit 7:47 %add) (wing 7:52 draft.m))
50+ (tuple 7:44 (lit 7:45 %add) (wing 7:50 draft.m))
51− (ctor 7:61 %acked))))))
51+ (ctor 7:59 %acked))))))
52− (arm 8:5
52+ (arm 8:3
53− (cell 8:5 (lit 8:6 %toggled) (bind 8:15 id))
53+ (cell 8:3 (lit 8:4 %toggled) (bind 8:13 id))
54− (tuple 8:20
54+ (tuple 8:18
55− (wing 8:21 m)
55+ (wing 8:19 m)
56− (list 8:23
56+ (list 8:21
57− (group 8:25
57+ (group 8:23
58− (call 8:26
58+ (call 8:24
59− (wing 8:26 poke.todo)
59+ (wing 8:24 poke.todo)
60− (tuple 8:36 (lit 8:37 %toggle) (wing 8:45 id))
60+ (tuple 8:34 (lit 8:35 %toggle) (wing 8:43 id))
61− (ctor 8:49 %acked))))))
61+ (ctor 8:47 %acked))))))
62− (arm 9:5
62+ (arm 9:3
63− (cell 9:5 (lit 9:6 %got) (bind 9:11 ts))
63+ (cell 9:3 (lit 9:4 %got) (bind 9:9 ts))
64− (tuple 9:20
64+ (tuple 9:18
65− (change 9:21 m
65+ (change 9:19 m
66− (edit 9:23 todos (wing 9:29 ts)))
66+ (edit 9:21 todos (wing 9:27 ts)))
67− (lit 9:33 ~)))
67+ (lit 9:31 ~)))
68− (arm 10:5
68+ (arm 10:3
69− (cell 10:5 (lit 10:6 %acked) (bind 10:13 err))
69+ (cell 10:3 (lit 10:4 %acked) (bind 10:11 err))
70− (tuple 10:20
70+ (tuple 10:18
71− (change 10:21 m
71+ (change 10:19 m
72− (edit 10:23 error (wing 10:29 err)))
72+ (edit 10:21 error (wing 10:27 err)))
73− (lit 10:34 ~))))))))
73+ (lit 10:32 ~))))))))
tests/golden/doc-grammar-02-buttons/source.jibbmode 100644 → 120000+1−7
@@ -1,7 +0,0 @@
1−:: /ui/components/buttons.jibb, a library with no main
2−++ add-button |= label=@t
3− button label %add :: error: nothing fixes the union of %add
4−++ labelled |= [label=@t msg=M]
5− button label msg :: fine: the caller's union
6−++ wide ^- (list attr)
7− ~[width+[%fill 1] pad+%s2] :: fine: the cast fixes the tags
@@ -0,0 +1 @@
1+../../../my-app/ui/components/buttons.jibb
tests/golden/doc-grammar-02-buttons/types.txt+1−1
@@ -1,4 +1,4 @@
1partial inference; module not checked
1partial inference; module not checked
2++ add-button: tag needs context in partial inference
2++ add-button: tag needs context in partial inference
3−++ labelled: $-([label=@t msg=A] (element A))
3+++ labelled: $-([label=@t msg=M] (element M))
4++ wide: (list attr)
4++ wide: (list attr)
tests/golden/doc-grammar-04-step/about.txt+1−1
@@ -1,4 +1,4 @@
1source: Grammar tab, section "Patterns", code block 4 of the tab
1source: 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
3expect: parses
3expect: parses
4expect-types: a partial inference report
4expect-types: a partial inference report
tests/golden/doc-grammar-04-step/source.jibb+5−5
@@ -7,8 +7,8 @@
7
7
8++ describe |= s=step
8++ describe |= s=step
9 ?- s
9 ?- s
10− [%move %left n] "left {n}"
10+ [%move %left n] "left {n}"
11− [%move %right n] "right {n}"
11+ [%move %right n] "right {n}"
12− [t %draft] t
12+ [t %draft] t
13− [t %sent sent-at] t
13+ [t %sent sent-at] t
14− %stop "stop"
14+ %stop "stop"
tests/golden/doc-grammar-04-step/tokens.txt+36−37
@@ -46,40 +46,39 @@
469:3 INDENT
469:3 INDENT
479:3 glyph ?-
479:3 glyph ?-
489:6 name s
489:6 name s
49−10:5 INDENT
49+10:3 NEWLINE
50−10:5 glyph [
50+10:3 glyph [
51−10:6 tight lit %move
51+10:4 tight lit %move
52−10:12 lit %left
52+10:10 lit %left
53−10:18 name n
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
54−10:19 tight glyph ]
63+11:18 tight glyph ]
55−10:23 str-head "left "
64+11:21 str-head "right "
65+11:29 tight name n
56−10:30 tight name n
66+11:30 tight str-tail ""
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
67+12:3 NEWLINE
68−12:5 glyph [
68+12:3 glyph [
69−12:6 tight name t
69+12:4 tight name t
70−12:8 lit %draft
70+12:6 lit %draft
71−12:14 tight glyph ]
71+12:12 tight glyph ]
72−12:23 name t
72+12:21 name t
73−13:5 NEWLINE
73+13:3 NEWLINE
74−13:5 glyph [
74+13:3 glyph [
75−13:6 tight name t
75+13:4 tight name t
76−13:8 lit %sent
76+13:6 lit %sent
77−13:14 name sent-at
77+13:12 name sent-at
78−13:21 tight glyph ]
78+13:19 tight glyph ]
79−13:23 name t
79+13:21 name t
80−14:5 NEWLINE
80+14:3 NEWLINE
81−14:5 lit %stop
81+14:3 lit %stop
82−14:23 str "stop"
82+14:21 str "stop"
83−14:29 DEDENT
83+14:27 DEDENT
84−14:29 DEDENT
85−14:29 NEWLINE
84+14:27 NEWLINE
tests/golden/doc-grammar-04-step/tree.txt+13−13
@@ -23,16 +23,16 @@
23 (body 9:3
23 (body 9:3
24 (branch 9:3
24 (branch 9:3
25 (wing 9:6 s)
25 (wing 9:6 s)
26− (arm 10:5
26+ (arm 10:3
27− (cell 10:5 (lit 10:6 %move) (lit 10:12 %left) (bind 10:18 n))
27+ (cell 10:3 (lit 10:4 %move) (lit 10:10 %left) (bind 10:16 n))
28− (str 10:23 "left " (wing 10:30 n)))
28+ (str 10:21 "left " (wing 10:28 n)))
29− (arm 11:5
29+ (arm 11:3
30− (cell 11:5 (lit 11:6 %move) (lit 11:12 %right) (bind 11:19 n))
30+ (cell 11:3 (lit 11:4 %move) (lit 11:10 %right) (bind 11:17 n))
31− (str 11:23 "right " (wing 11:31 n)))
31+ (str 11:21 "right " (wing 11:29 n)))
32− (arm 12:5
32+ (arm 12:3
33− (cell 12:5 (bind 12:6 t) (lit 12:8 %draft))
33+ (cell 12:3 (bind 12:4 t) (lit 12:6 %draft))
34− (wing 12:23 t))
34+ (wing 12:21 t))
35− (arm 13:5
35+ (arm 13:3
36− (cell 13:5 (bind 13:6 t) (lit 13:8 %sent) (bind 13:14 sent-at))
36+ (cell 13:3 (bind 13:4 t) (lit 13:6 %sent) (bind 13:12 sent-at))
37− (wing 13:23 t))
37+ (wing 13:21 t))
38− (arm 14:5 (lit 14:5 %stop) (str 14:23 "stop")))))))
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 @@
1source: Grammar tab, section "Example: a store and an island", code block 6 of the tab (block 5 is the EBNF)
1source: 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))`
3expect: parses
3expect: parses
4expect-types: a partial inference report; store kind and declaration scope remain unresolved
4expect-types: a partial inference report; store kind and declaration scope remain unresolved
tests/golden/doc-grammar-06-cart-store/source.jibbmode 100644 → 120000+1−12
@@ -1,12 +0,0 @@
1−:: /ui/stores/cart.jibb
2−+$ state [items=(list @t) open=?]
3−+$ poke
4− [%add item=@t]
5− %toggle
6−
7−++ main (store init update)
8−++ init ^- state [~ %.n]
9−++ update |= [a=poke s=state]
10− ?- a
11− [%add item] s(items=[item items.s])
12− %toggle s(open=(not open.s))
@@ -0,0 +1 @@
1+../../../my-app/ui/stores/cart.jibb
tests/golden/doc-grammar-06-cart-store/tokens.txt+34−31
@@ -38,9 +38,13 @@
388:9 glyph ^-
388:9 glyph ^-
398:12 name state
398:12 name state
408:18 glyph [
408:18 glyph [
41−8:19 tight lit ~
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 =
42−8:21 lit %.n
46+8:32 tight lit %.n
43−8:24 tight glyph ]
47+8:35 tight glyph ]
449:1 NEWLINE
489:1 NEWLINE
459:1 glyph ++
499:1 glyph ++
469:4 name update
509:4 name update
@@ -56,31 +60,30 @@
5610:3 INDENT
6010:3 INDENT
5710:3 glyph ?-
6110:3 glyph ?-
5810:6 name a
6210:6 name a
59−11:5 INDENT
63+11:3 NEWLINE
60−11:5 glyph [
64+11:3 glyph [
61−11:6 tight lit %add
65+11:4 tight lit %add
62−11:11 name item
66+11:9 name item
63−11:15 tight glyph ]
67+11:13 tight glyph ]
64−11:18 name s
68+11:16 name s
65−11:19 tight glyph (
69+11:17 tight glyph (
66−11:20 tight name items
70+11:18 tight name items
67−11:25 tight glyph =
71+11:23 tight glyph =
68−11:26 tight glyph [
72+11:24 tight glyph [
69−11:27 tight name item
73+11:25 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
74+11:30 wing items.s
82−12:36 tight glyph )
83−12:37 tight glyph )
75+11:37 tight glyph ]
84−12:38 DEDENT
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 )
85−12:38 DEDENT
88+12:36 DEDENT
86−12:38 NEWLINE
89+12:36 NEWLINE
tests/golden/doc-grammar-06-cart-store/tree.txt+14−12
@@ -16,7 +16,9 @@
16 (value 8:1 init
16 (value 8:1 init
17 (cast 8:9
17 (cast 8:9
18 (ref 8:12 state)
18 (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)))))
20 (value 9:1 update
22 (value 9:1 update
21 (gate 9:11
23 (gate 9:11
22 (cell 9:14
24 (cell 9:14
@@ -25,14 +27,14 @@
25 (body 10:3
27 (body 10:3
26 (branch 10:3
28 (branch 10:3
27 (wing 10:6 a)
29 (wing 10:6 a)
28− (arm 11:5
30+ (arm 11:3
29− (cell 11:5 (lit 11:6 %add) (bind 11:11 item))
31+ (cell 11:3 (lit 11:4 %add) (bind 11:9 item))
30− (change 11:18 s
32+ (change 11:16 s
31− (edit 11:20 items
33+ (edit 11:18 items
32− (tuple 11:26 (wing 11:27 item) (wing 11:32 items.s)))))
34+ (tuple 11:24 (wing 11:25 item) (wing 11:30 items.s)))))
33− (arm 12:5
35+ (arm 12:3
34− (lit 12:5 %toggle)
36+ (lit 12:3 %toggle)
35− (change 12:18 s
37+ (change 12:16 s
36− (edit 12:20 open
38+ (edit 12:18 open
37− (group 12:25
39+ (group 12:23
38− (call 12:26 (wing 12:26 not) (wing 12:30 open.s)))))))))))
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 @@
1source: Grammar tab, section "Example: a store and an island", code block 7 of the tab
1source: 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`
3expect: parses
3expect: parses
tests/golden/doc-grammar-07-basket/source.jibbmode 100644 → 120000+1−32
@@ -1,32 +0,0 @@
1−:: /ui/basket.jibb
2−/= cart /ui/stores/cart
3−
4−++ main (program init update view subs)
5−
6−+$ model [cart=state.cart note=@t]
7−+$ msg
8− [%noted text=@t]
9− %add
10− %toggle
11− [%got cart=state.cart]
12− [%acked err=(unit @t)]
13−
14−++ init |= ~
15− [[~ %.n] ""]
16−
17−++ update |= [=msg m=model]
18− ?- 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 ~]
24−
25−++ subs |= m=model
26− ~[[%watch (state.cart |=%got)]]
27−
28−++ view |= m=model
29− column ~[gap+%s1] ~[
30− (text "{(lent items.cart.m)} items")
31− field "Item" note.m |=%noted
32− button "Add" %add
@@ -0,0 +1 @@
1+../../../my-app/ui/basket.jibb
tests/golden/doc-grammar-07-basket/tokens.txt+85−78
@@ -66,12 +66,20 @@
6614:12 lit ~
6614:12 lit ~
6715:3 INDENT
6715:3 INDENT
6815:3 glyph [
6815:3 glyph [
69−15:4 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 =
70−15:5 tight lit ~
74+15:16 tight lit ~
75+15:18 name open
76+15:22 tight glyph =
71−15:7 lit %.n
77+15:23 tight lit %.n
72−15:10 tight glyph ]
78+15:26 tight glyph ]
73−15:12 str ""
79+15:28 name note
80+15:32 tight glyph =
81+15:33 tight str ""
74−15:14 tight glyph ]
82+15:35 tight glyph ]
7517:1 DEDENT
8317:1 DEDENT
7617:1 NEWLINE
8417:1 NEWLINE
7717:1 glyph ++
8517:1 glyph ++
@@ -87,78 +95,77 @@
8718:3 INDENT
9518:3 INDENT
8818:3 glyph ?-
9618:3 glyph ?-
8918:6 name msg
9718:6 name msg
90−19:5 INDENT
98+19:3 NEWLINE
91−19:5 glyph [
99+19:3 glyph [
92−19:6 tight lit %noted
100+19:4 tight lit %noted
93−19:13 name t
101+19:11 name t
94−19:14 tight glyph ]
102+19:12 tight glyph ]
95−19:20 glyph [
103+19:18 glyph [
96−19:21 tight name m
104+19:19 tight name m
97−19:22 tight glyph (
105+19:20 tight glyph (
98−19:23 tight name note
106+19:21 tight name note
99−19:27 tight glyph =
107+19:25 tight glyph =
100−19:28 tight name t
108+19:26 tight name t
101−19:29 tight glyph )
109+19:27 tight glyph )
102−19:31 lit ~
110+19:29 lit ~
103−19:32 tight glyph ]
111+19:30 tight glyph ]
104−20:5 NEWLINE
112+20:3 NEWLINE
105−20:5 lit %add
113+20:3 lit %add
106−20:20 glyph [
114+20:18 glyph [
107−20:21 tight name m
115+20:19 tight name m
108−20:22 tight glyph (
116+20:20 tight glyph (
109−20:23 tight name note
117+20:21 tight name note
110−20:27 tight glyph =
118+20:25 tight glyph =
111−20:28 tight str ""
119+20:26 tight str ""
112−20:30 tight glyph )
120+20:28 tight glyph )
113−20:32 glyph ~[
121+20:30 glyph ~[
114−20:34 tight glyph (
122+20:32 tight glyph (
115−20:35 tight wing poke.cart
123+20:33 tight wing poke.cart
116−20:45 glyph [
124+20:43 glyph [
117−20:46 tight lit %add
125+20:44 tight lit %add
118−20:51 wing note.m
126+20:49 wing note.m
127+20:55 tight glyph ]
119−20:57 tight glyph ]
128+20:57 glyph |=
129+20:59 tight lit %acked
120−20:59 glyph |=
130+20:65 tight glyph )
121−20:61 tight lit %acked
131+20:66 tight glyph ]
122−20:67 tight glyph )
132+20:67 tight glyph ]
123−20:68 tight glyph ]
124−20:69 tight glyph ]
125−21:5 NEWLINE
133+21:3 NEWLINE
126−21:5 lit %toggle
134+21:3 lit %toggle
127−21:20 glyph [
135+21:18 glyph [
128−21:21 tight name m
136+21:19 tight name m
129−21:23 glyph ~[
137+21:21 glyph ~[
130−21:25 tight glyph (
138+21:23 tight glyph (
131−21:26 tight wing poke.cart
139+21:24 tight wing poke.cart
132−21:36 lit %toggle
140+21:34 lit %toggle
133−21:44 glyph |=
141+21:42 glyph |=
134−21:46 tight lit %acked
142+21:44 tight lit %acked
143+21:50 tight glyph )
144+21:51 tight glyph ]
135−21:52 tight glyph )
145+21:52 tight glyph ]
136−21:53 tight glyph ]
137−21:54 tight glyph ]
138−22:5 NEWLINE
146+22:3 NEWLINE
139−22:5 glyph [
147+22:3 glyph [
140−22:6 tight lit %got
148+22:4 tight lit %got
141−22:11 name c
149+22:9 name c
142−22:12 tight glyph ]
150+22:10 tight glyph ]
143−22:20 glyph [
151+22:18 glyph [
144−22:21 tight name m
152+22:19 tight name m
145−22:22 tight glyph (
153+22:20 tight glyph (
146−22:23 tight name cart
154+22:21 tight name cart
147−22:27 tight glyph =
155+22:25 tight glyph =
148−22:28 tight name c
156+22:26 tight name c
149−22:29 tight glyph )
157+22:27 tight glyph )
150−22:31 lit ~
158+22:29 lit ~
151−22:32 tight glyph ]
159+22:30 tight glyph ]
152−23:5 NEWLINE
160+23:3 NEWLINE
153−23:5 glyph [
161+23:3 glyph [
154−23:6 tight lit %acked
162+23:4 tight lit %acked
155−23:13 name err
163+23:11 name err
156−23:16 tight glyph ]
164+23:14 tight glyph ]
157−23:20 glyph [
165+23:18 glyph [
158−23:21 tight name m
166+23:19 tight name m
159−23:23 lit ~
167+23:21 lit ~
160−23:24 tight glyph ]
168+23:22 tight glyph ]
161−25:1 DEDENT
16225:1 DEDENT
16925:1 DEDENT
16325:1 NEWLINE
17025:1 NEWLINE
16425:1 glyph ++
17125:1 glyph ++
tests/golden/doc-grammar-07-basket/tree.txt+38−35
@@ -26,8 +26,11 @@
26 (const 14:12 ~)
26 (const 14:12 ~)
27 (body 15:3
27 (body 15:3
28 (tuple 15:3
28 (tuple 15:3
29− (tuple 15:4 (lit 15:5 ~) (lit 15:7 %.n))
29+ (face 15:4 cart
30− (str 15:12 "")))))
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 ""))))))
31 (value 17:1 update
34 (value 17:1 update
32 (gate 17:11
35 (gate 17:11
33 (cell 17:14
36 (cell 17:14
@@ -36,39 +39,39 @@
36 (body 18:3
39 (body 18:3
37 (branch 18:3
40 (branch 18:3
38 (wing 18:6 msg)
41 (wing 18:6 msg)
39− (arm 19:5
42+ (arm 19:3
40− (cell 19:5 (lit 19:6 %noted) (bind 19:13 t))
43+ (cell 19:3 (lit 19:4 %noted) (bind 19:11 t))
41− (tuple 19:20
44+ (tuple 19:18
42− (change 19:21 m
45+ (change 19:19 m
43− (edit 19:23 note (wing 19:28 t)))
46+ (edit 19:21 note (wing 19:26 t)))
44− (lit 19:31 ~)))
47+ (lit 19:29 ~)))
45− (arm 20:5
48+ (arm 20:3
46− (lit 20:5 %add)
49+ (lit 20:3 %add)
47− (tuple 20:20
50+ (tuple 20:18
48− (change 20:21 m
51+ (change 20:19 m
49− (edit 20:23 note (str 20:28 "")))
52+ (edit 20:21 note (str 20:26 "")))
50− (list 20:32
53+ (list 20:30
51− (group 20:34
54+ (group 20:32
52− (call 20:35
55+ (call 20:33
53− (wing 20:35 poke.cart)
56+ (wing 20:33 poke.cart)
54− (tuple 20:45 (lit 20:46 %add) (wing 20:51 note.m))
57+ (tuple 20:43 (lit 20:44 %add) (wing 20:49 note.m))
55− (ctor 20:59 %acked))))))
58+ (ctor 20:57 %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
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
64− (cell 22:5 (lit 22:6 %got) (bind 22:11 c))
67+ (cell 22:3 (lit 22:4 %got) (bind 22:9 c))
65− (tuple 22:20
68+ (tuple 22:18
66− (change 22:21 m
69+ (change 22:19 m
67− (edit 22:23 cart (wing 22:28 c)))
70+ (edit 22:21 cart (wing 22:26 c)))
68− (lit 22:31 ~)))
71+ (lit 22:29 ~)))
69− (arm 23:5
72+ (arm 23:3
70− (cell 23:5 (lit 23:6 %acked) (bind 23:13 err))
73+ (cell 23:3 (lit 23:4 %acked) (bind 23:11 err))
71− (tuple 23:20 (wing 23:21 m) (lit 23:23 ~)))))))
74+ (tuple 23:18 (wing 23:19 m) (lit 23:21 ~)))))))
72 (value 25:1 subs
75 (value 25:1 subs
73 (gate 25:9
76 (gate 25:9
74 (face 25:12 m (ref 25:14 model))
77 (face 25:12 m (ref 25:14 model))
tests/golden/doc-overview-02-theme/source.jibbmode 100644 → 120000+1−8
@@ -1,8 +0,0 @@
1−++ theme ^- theme
2− [ space=[s1="4px" s2="8px" s3="16px"]
3− tones=[normal="#222" background="#fff" accent="#17734f" danger="#b3261e" muted="#5f5f5f"]
4− wide="60rem"
5− lang="en"
6− zone="UTC"
7− font=`%/static/fonts/inter.woff2
8− dark=`[tones=[normal="#eee" background="#111" accent="#4c9" danger="#f28b82" muted="#aaa"]]
@@ -0,0 +1 @@
1+../../../my-app/ui/theme.jibb
tests/golden/doc-overview-04-todo-api/source.jibbmode 100644 → 120000+1−13
@@ -1,13 +0,0 @@
1−:: /ui/api/todo.jibb
2−/- todo
3−/% %todo-action
4−/% %todos
5−/% %todo-update
6−/% %todo-item
7−
8−+$ item item.todo
9−+$ poke todo-action
10−+$ paths
11− [%todos /todos todos]
12− [%changes /changes (facts todos todo-update)]
13− [%todo-by-id /todo/[id=@ud] todo-item]
@@ -0,0 +1 @@
1+../../../my-app/ui/api/todo.jibb
tests/golden/doc-overview-08-about/source.jibbmode 100644 → 120000+1−7
@@ -1,7 +0,0 @@
1−++ main view
2−
3−++ view
4− column ~[width+[%fill 1] pad+%s3 gap+%s2] ~[
5− heading 1 "About this ship"
6− para ~[(text "Hosted on Urbit. This page ships no JavaScript.")]
7− el ~[tone+%accent] (link %/blog "Read the blog")
@@ -0,0 +1 @@
1+../../../my-app/ui/about.jibb
tests/golden/doc-overview-09-blog-index/source.jibbmode 100644 → 120000+1−9
@@ -1,9 +0,0 @@
1−/- blog
2−/= api /ui/api/blog
3−/= card /ui/components/card
4−
5−++ main (page load view)
6−++ load |=(~ (posts.api same))
7−
8−++ view |= ps=(list post.blog)
9− column ~[gap+%s2] (turn ps card.card)
@@ -0,0 +1 @@
1+../../../my-app/ui/blog/index.jibb
tests/golden/doc-overview-10-todo-list/about.txt+1−1
@@ -1,3 +1,3 @@
1source: 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
1source: 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
3expect: parses
3expect: parses
tests/golden/doc-overview-10-todo-list/source.jibbmode 100644 → 120000+1−40
@@ -1,40 +0,0 @@
1−/= todo /ui/api/todo
2−
3−++ main (program init update view subs)
4−
5−+$ model [todos=(list item.todo) draft=@t error=(unit @t)]
6−+$ msg
7− [%typed text=@t]
8− %submit
9− [%toggled id=@ud]
10− [%got todos=(list item.todo)]
11− [%acked err=(unit @t)]
12−
13−++ init |= ts=(list item.todo)
14− [ts "" ~]
15−
16−++ update |= [=msg m=model]
17− ?- 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) ~]
26−
27−++ subs |= m=model
28− ~[[%watch (todos.todo |=%got)]]
29−
30−++ view |= m=model
31− column ~[gap+%s2] ~[
32− heading 2 "Todos"
33− each (turn todos.m row-of)
34− row ~[gap+%s1] ~[
35− el ~[width+[%fill 1]] (field "New todo" draft.m |=%typed)
36− button "Add" %submit
37− el ~[tone+%danger] (text (fall error.m ""))
38−
39−++ row-of |= t=item.todo
40− [id.t (toggle done.t text.t [%toggled id.t])]
@@ -0,0 +1 @@
1+../../../my-app/ui/todo-list.jibb
tests/golden/doc-overview-10-todo-list/tokens.txt+128−124
@@ -88,10 +88,16 @@
8813:30 tight glyph )
8813:30 tight glyph )
8914:3 INDENT
8914:3 INDENT
9014:3 glyph [
9014:3 glyph [
91−14:4 tight name ts
91+14:4 tight name todos
92−14:7 str ""
92+14:9 tight glyph =
93−14:10 lit ~
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 ~
94−14:11 tight glyph ]
100+14:29 tight glyph ]
9516:1 DEDENT
10116:1 DEDENT
9616:1 NEWLINE
10216:1 NEWLINE
9716:1 glyph ++
10316:1 glyph ++
@@ -107,127 +113,125 @@
10717:3 INDENT
11317:3 INDENT
10817:3 glyph ?-
11417:3 glyph ?-
10917:6 name msg
11517:6 name msg
110−18:5 INDENT
116+18:3 NEWLINE
111−18:5 glyph [
117+18:3 glyph [
112−18:6 tight lit %typed
118+18:4 tight lit %typed
113−18:13 name t
119+18:11 name t
114−18:14 tight glyph ]
120+18:12 tight glyph ]
115−19:7 INDENT
121+19:5 INDENT
116−19:7 glyph ?-
122+19:5 glyph ?-
117−19:10 glyph (
123+19:8 glyph (
118−19:11 tight name gth
124+19:9 tight name gth
119−19:15 glyph (
125+19:13 glyph (
120−19:16 tight name lent
126+19:14 tight name lent
121−19:21 glyph (
127+19:19 glyph (
122−19:22 tight name tuba
128+19:20 tight name tuba
123−19:27 glyph (
129+19:25 glyph (
124−19:28 tight name trip
130+19:26 tight name trip
125−19:33 name t
131+19:31 name t
132+19:32 tight glyph )
133+19:33 tight glyph )
12619:34 tight glyph )
13419:34 tight glyph )
127−19:35 tight glyph )
128−19:36 tight glyph )
129−19:38 lit 80
135+19:36 lit 80
130−19:40 tight glyph )
136+19:38 tight glyph )
131−20:9 INDENT
137+20:5 NEWLINE
132−20:9 lit %.y
138+20:5 lit %.y
133−20:14 glyph [
139+20:10 glyph [
134−20:15 tight name m
140+20:11 tight name m
135−20:16 tight glyph (
141+20:12 tight glyph (
136−20:17 tight name draft
142+20:13 tight name draft
137−20:22 tight glyph =
143+20:18 tight glyph =
138−20:23 tight name t
144+20:19 tight name t
139−20:25 name error
145+20:21 name error
140−20:30 tight glyph =
146+20:26 tight glyph =
141−20:31 tight glyph `
147+20:27 tight glyph `
142−20:32 tight str "Too long"
148+20:28 tight str "Too long"
143−20:42 tight glyph )
149+20:38 tight glyph )
144−20:44 lit ~
150+20:40 lit ~
145−20:45 tight glyph ]
151+20:41 tight glyph ]
146−21:9 NEWLINE
152+21:5 NEWLINE
147−21:9 lit %.n
153+21:5 lit %.n
148−21:14 glyph [
154+21:10 glyph [
149−21:15 tight name m
155+21:11 tight name m
150−21:16 tight glyph (
156+21:12 tight glyph (
151−21:17 tight name draft
157+21:13 tight name draft
152−21:22 tight glyph =
158+21:18 tight glyph =
153−21:23 tight name t
159+21:19 tight name t
154−21:25 name error
160+21:21 name error
155−21:30 tight glyph =
161+21:26 tight glyph =
156−21:31 tight lit ~
162+21:27 tight lit ~
157−21:32 tight glyph )
163+21:28 tight glyph )
158−21:34 lit ~
164+21:30 lit ~
159−21:35 tight glyph ]
165+21:31 tight glyph ]
160−22:5 DEDENT
166+22:3 DEDENT
161−22:5 DEDENT
162−22:5 NEWLINE
167+22:3 NEWLINE
163−22:5 lit %submit
168+22:3 lit %submit
164−22:20 glyph [
169+22:18 glyph [
165−22:21 tight name m
170+22:19 tight name m
166−22:22 tight glyph (
171+22:20 tight glyph (
167−22:23 tight name draft
172+22:21 tight name draft
168−22:28 tight glyph =
173+22:26 tight glyph =
169−22:29 tight str ""
174+22:27 tight str ""
170−22:31 tight glyph )
175+22:29 tight glyph )
171−22:33 glyph ~[
176+22:31 glyph ~[
172−22:35 tight glyph (
177+22:33 tight glyph (
173−22:36 tight wing poke.todo
178+22:34 tight wing poke.todo
174−22:46 glyph [
179+22:44 glyph [
175−22:47 tight lit %add
180+22:45 tight lit %add
176−22:52 wing draft.m
181+22:50 wing draft.m
177−22:59 tight glyph ]
182+22:57 tight glyph ]
183+22:59 glyph |=
184+22:61 tight lit %acked
178−22:61 glyph |=
185+22:67 tight glyph )
179−22:63 tight lit %acked
186+22:68 tight glyph ]
180−22:69 tight glyph )
187+22:69 tight glyph ]
181−22:70 tight glyph ]
182−22:71 tight glyph ]
183−23:5 NEWLINE
188+23:3 NEWLINE
184−23:5 glyph [
189+23:3 glyph [
185−23:6 tight lit %toggled
190+23:4 tight lit %toggled
186−23:15 name id
191+23:13 name id
187−23:17 tight glyph ]
192+23:15 tight glyph ]
188−23:20 glyph [
193+23:18 glyph [
189−23:21 tight name m
194+23:19 tight name m
190−23:23 glyph ~[
195+23:21 glyph ~[
191−23:25 tight glyph (
196+23:23 tight glyph (
192−23:26 tight wing poke.todo
197+23:24 tight wing poke.todo
193−23:36 glyph [
198+23:34 glyph [
194−23:37 tight lit %toggle
199+23:35 tight lit %toggle
195−23:45 name id
200+23:43 name id
196−23:47 tight glyph ]
201+23:45 tight glyph ]
197−23:49 glyph |=
202+23:47 glyph |=
198−23:51 tight lit %acked
203+23:49 tight lit %acked
199−23:57 tight glyph )
204+23:55 tight glyph )
200−23:58 tight glyph ]
205+23:56 tight glyph ]
201−23:59 tight glyph ]
206+23:57 tight glyph ]
202−24:5 NEWLINE
207+24:3 NEWLINE
203−24:5 glyph [
208+24:3 glyph [
204−24:6 tight lit %got
209+24:4 tight lit %got
205−24:11 name ts
210+24:9 name ts
206−24:13 tight glyph ]
211+24:11 tight glyph ]
207−24:20 glyph [
212+24:18 glyph [
208−24:21 tight name m
213+24:19 tight name m
209−24:22 tight glyph (
214+24:20 tight glyph (
210−24:23 tight name todos
215+24:21 tight name todos
211−24:28 tight glyph =
216+24:26 tight glyph =
212−24:29 tight name ts
217+24:27 tight name ts
213−24:31 tight glyph )
218+24:29 tight glyph )
214−24:33 lit ~
219+24:31 lit ~
215−24:34 tight glyph ]
220+24:32 tight glyph ]
216−25:5 NEWLINE
221+25:3 NEWLINE
217−25:5 glyph [
222+25:3 glyph [
218−25:6 tight lit %acked
223+25:4 tight lit %acked
219−25:13 name err
224+25:11 name err
220−25:16 tight glyph ]
225+25:14 tight glyph ]
221−25:20 glyph [
226+25:18 glyph [
222−25:21 tight name m
227+25:19 tight name m
223−25:22 tight glyph (
228+25:20 tight glyph (
224−25:23 tight name error
229+25:21 tight name error
225−25:28 tight glyph =
230+25:26 tight glyph =
226−25:29 tight name err
231+25:27 tight name err
227−25:32 tight glyph )
232+25:30 tight glyph )
228−25:34 lit ~
233+25:32 lit ~
229−25:35 tight glyph ]
234+25:33 tight glyph ]
230−27:1 DEDENT
23127:1 DEDENT
23527:1 DEDENT
23227:1 NEWLINE
23627:1 NEWLINE
23327:1 glyph ++
23727:1 glyph ++
tests/golden/doc-overview-10-todo-list/tree.txt+68−65
@@ -32,7 +32,10 @@
32 (face 13:12 ts
32 (face 13:12 ts
33 (apply 13:15 list (ref 13:21 item.todo)))
33 (apply 13:15 list (ref 13:21 item.todo)))
34 (body 14:3
34 (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 ~))))))
36 (value 16:1 update
39 (value 16:1 update
37 (gate 16:11
40 (gate 16:11
38 (cell 16:14
41 (cell 16:14
@@ -41,70 +44,70 @@
41 (body 17:3
44 (body 17:3
42 (branch 17:3
45 (branch 17:3
43 (wing 17:6 msg)
46 (wing 17:6 msg)
44− (arm 18:5
47+ (arm 18:3
45− (cell 18:5 (lit 18:6 %typed) (bind 18:13 t))
48+ (cell 18:3 (lit 18:4 %typed) (bind 18:11 t))
46− (body 19:7
49+ (body 19:5
47− (branch 19:7
50+ (branch 19:5
48− (group 19:10
51+ (group 19:8
49− (call 19:11
52+ (call 19:9
50− (wing 19:11 gth)
53+ (wing 19:9 gth)
51− (group 19:15
54+ (group 19:13
52− (call 19:16
55+ (call 19:14
53− (wing 19:16 lent)
56+ (wing 19:14 lent)
54− (group 19:21
57+ (group 19:19
55− (call 19:22
58+ (call 19:20
56− (wing 19:22 tuba)
59+ (wing 19:20 tuba)
57− (group 19:27
60+ (group 19:25
58− (call 19:28 (wing 19:28 trip) (wing 19:33 t)))))))
61+ (call 19:26 (wing 19:26 trip) (wing 19:31 t)))))))
59− (lit 19:38 80)))
62+ (lit 19:36 80)))
60− (arm 20:9
63+ (arm 20:5
61− (lit 20:9 %.y)
64+ (lit 20:5 %.y)
62− (tuple 20:14
65+ (tuple 20:10
63− (change 20:15 m
66+ (change 20:11 m
64− (edit 20:17 draft (wing 20:23 t))
67+ (edit 20:13 draft (wing 20:19 t))
65− (edit 20:25 error
68+ (edit 20:21 error
66− (unit 20:31 (str 20:32 "Too long"))))
69+ (unit 20:27 (str 20:28 "Too long"))))
67− (lit 20:44 ~)))
70+ (lit 20:40 ~)))
68− (arm 21:9
71+ (arm 21:5
69− (lit 21:9 %.n)
72+ (lit 21:5 %.n)
70− (tuple 21:14
73+ (tuple 21:10
71− (change 21:15 m
74+ (change 21:11 m
72− (edit 21:17 draft (wing 21:23 t))
75+ (edit 21:13 draft (wing 21:19 t))
73− (edit 21:25 error (lit 21:31 ~)))
76+ (edit 21:21 error (lit 21:27 ~)))
74− (lit 21:34 ~))))))
77+ (lit 21:30 ~))))))
75− (arm 22:5
78+ (arm 22:3
76− (lit 22:5 %submit)
79+ (lit 22:3 %submit)
77− (tuple 22:20
80+ (tuple 22:18
78− (change 22:21 m
81+ (change 22:19 m
79− (edit 22:23 draft (str 22:29 "")))
82+ (edit 22:21 draft (str 22:27 "")))
80− (list 22:33
83+ (list 22:31
81− (group 22:35
84+ (group 22:33
82− (call 22:36
85+ (call 22:34
83− (wing 22:36 poke.todo)
86+ (wing 22:34 poke.todo)
84− (tuple 22:46 (lit 22:47 %add) (wing 22:52 draft.m))
87+ (tuple 22:44 (lit 22:45 %add) (wing 22:50 draft.m))
85− (ctor 22:61 %acked))))))
88+ (ctor 22:59 %acked))))))
86− (arm 23:5
89+ (arm 23:3
87− (cell 23:5 (lit 23:6 %toggled) (bind 23:15 id))
90+ (cell 23:3 (lit 23:4 %toggled) (bind 23:13 id))
88− (tuple 23:20
91+ (tuple 23:18
89− (wing 23:21 m)
92+ (wing 23:19 m)
90− (list 23:23
93+ (list 23:21
91− (group 23:25
94+ (group 23:23
92− (call 23:26
95+ (call 23:24
93− (wing 23:26 poke.todo)
96+ (wing 23:24 poke.todo)
94− (tuple 23:36 (lit 23:37 %toggle) (wing 23:45 id))
97+ (tuple 23:34 (lit 23:35 %toggle) (wing 23:43 id))
95− (ctor 23:49 %acked))))))
98+ (ctor 23:47 %acked))))))
96− (arm 24:5
99+ (arm 24:3
97− (cell 24:5 (lit 24:6 %got) (bind 24:11 ts))
100+ (cell 24:3 (lit 24:4 %got) (bind 24:9 ts))
98− (tuple 24:20
101+ (tuple 24:18
99− (change 24:21 m
102+ (change 24:19 m
100− (edit 24:23 todos (wing 24:29 ts)))
103+ (edit 24:21 todos (wing 24:27 ts)))
101− (lit 24:33 ~)))
104+ (lit 24:31 ~)))
102− (arm 25:5
105+ (arm 25:3
103− (cell 25:5 (lit 25:6 %acked) (bind 25:13 err))
106+ (cell 25:3 (lit 25:4 %acked) (bind 25:11 err))
104− (tuple 25:20
107+ (tuple 25:18
105− (change 25:21 m
108+ (change 25:19 m
106− (edit 25:23 error (wing 25:29 err)))
109+ (edit 25:21 error (wing 25:27 err)))
107− (lit 25:34 ~)))))))
110+ (lit 25:32 ~)))))))
108 (value 27:1 subs
111 (value 27:1 subs
109 (gate 27:9
112 (gate 27:9
110 (face 27:12 m (ref 27:14 model))
113 (face 27:12 m (ref 27:14 model))
tests/golden/doc-overview-11-index/source.jibbmode 100644 → 120000+1−10
@@ -1,10 +0,0 @@
1−/= todo /ui/api/todo
2−/= todo-list /ui/todo-list
3−
4−++ main (page load view)
5−++ load |=(~ (todos.todo same))
6−
7−++ view |= ts=(list item.todo)
8− column ~[pad+%s3] ~[
9− heading 1 "My ship"
10− island main.todo-list ts
@@ -0,0 +1 @@
1+../../../my-app/ui/index.jibb
tests/golden/fixture-blog-api/source.jibbmode 100644 → 120000+1−5
@@ -1,5 +0,0 @@
1−:: Fixture for the documented examples; not supplied by the design doc.
2−/% %posts
3−
4−+$ paths
5− [%posts /posts posts]
@@ -0,0 +1 @@
1+../../../my-app/ui/api/blog.jibb
tests/golden/fixture-blog-card/source.jibbmode 100644 → 120000+1−5
@@ -1,5 +0,0 @@
1−:: Fixture for the documented examples; not supplied by the design doc.
2−/- blog
3−
4−++ card |= p=post.blog
5− text title.p
@@ -0,0 +1 @@
1+../../../my-app/ui/components/card.jibb
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"
2tests: the decimal literal 1.000
2tests: the decimal literal 1.000
3expect: parses
3expect: 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

This diff is too big to show here.

tests/golden/lex-body-rest-ok-8/tokens.txtnew file+63

This diff is too big to show here.

tests/golden/lex-body-rest-ok-8/tree.txtnew file+32

This diff is too big to show here.

tests/golden/lex-body-rest-ok-8/types.txtnew file+3

This diff is too big to show here.

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

This diff is too big to show here.

tests/golden/lex-layout-bad-4/tree.txt+1−1

This diff is too big to show here.

tests/golden/lex-name-bad-5/tokens.txt+4−3

This diff is too big to show here.

tests/golden/lex-name-bad-5/tree.txt+1−1

This diff is too big to show here.

tests/golden/lex-rune-layout-bad-3/about.txtdeleted−3

This diff is too big to show here.

tests/golden/lex-rune-layout-bad-3/tree.txtdeleted−3

This diff is too big to show here.

tests/golden/lex-rune-layout-ok-3/about.txtnew file+3

This diff is too big to show here.

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

This diff is too big to show here.

tests/golden/lex-tight-change-bad-10/about.txtnew file+3

This diff is too big to show here.

tests/golden/lex-tight-change-bad-10/source.jibbnew file+1

This diff is too big to show here.

tests/golden/lex-tight-change-bad-10/tokens.txtnew file+7

This diff is too big to show here.

tests/golden/lex-tight-change-bad-10/tree.txtnew file+3

This diff is too big to show here.

tests/golden/lex-tight-change-bad-11/about.txtnew file+3

This diff is too big to show here.

tests/golden/lex-tight-change-bad-11/source.jibbnew file+2

This diff is too big to show here.

tests/golden/lex-tight-change-bad-11/tokens.txtnew file+9

This diff is too big to show here.

tests/golden/lex-tight-change-bad-11/tree.txtnew file+3

This diff is too big to show here.

tests/golden/lex-tight-change-bad-5/about.txt+3−3

This diff is too big to show here.

tests/golden/lex-tight-change-bad-5/source.jibb+1−1

This diff is too big to show here.

tests/golden/lex-tight-change-bad-5/tokens.txt+1−2

This diff is too big to show here.

tests/golden/lex-tight-change-bad-5/tree.txt+3−3

This diff is too big to show here.

tests/golden/lex-tight-change-ok-2/about.txtnew file+3

This diff is too big to show here.

tests/golden/lex-tight-change-ok-2/source.jibbnew file+7

This diff is too big to show here.

tests/golden/lex-tight-change-ok-2/tokens.txtnew file+55

This diff is too big to show here.

tests/golden/lex-tight-change-ok-2/tree.txtnew file+20

This diff is too big to show here.

tests/golden/lex-typevar-bad-1/about.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-1/source.jibbnew file+1

This diff is too big to show here.

tests/golden/lex-typevar-bad-1/tokens.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-1/tree.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-2/about.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-2/source.jibbnew file+1

This diff is too big to show here.

tests/golden/lex-typevar-bad-2/tokens.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-2/tree.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-3/about.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-3/source.jibbnew file+1

This diff is too big to show here.

tests/golden/lex-typevar-bad-3/tokens.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-3/tree.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-4/about.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-4/source.jibbnew file+1

This diff is too big to show here.

tests/golden/lex-typevar-bad-4/tokens.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-bad-4/tree.txtnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-ok-1/about.txtnew file+4

This diff is too big to show here.

tests/golden/lex-typevar-ok-1/source.jibbnew file+3

This diff is too big to show here.

tests/golden/lex-typevar-ok-1/tokens.txtnew file+39

This diff is too big to show here.

tests/golden/lex-typevar-ok-1/tree.txtnew file+15

This diff is too big to show here.

tests/golden/lex-typevar-ok-1/types.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/module-trees.txtnew file+8

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/modules/ui/api/demo.jibbnew file+5

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-derived-clash/types.txtnew file+8

This diff is too big to show here.

tests/golden/module-import-api-import-error/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-import-error/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-import-error/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-import-error/module-trees.txtnew file+48

This diff is too big to show here.

tests/golden/module-import-api-import-error/modules.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-import-error/modules/ui/api/demo.jibbnew file+5

This diff is too big to show here.

tests/type-store/cart.txt → tests/golden/module-import-api-import-error/modules/ui/stores/cart.jibbrenamed+1−1

This diff is too big to show here.

tests/golden/module-import-api-import-error/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-import-error/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-import-error/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-import-error/types.txtnew file+8

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/mar/same.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/module-trees.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/modules/ui/api/demo.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-mark-prelude-value/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-mark-value/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-mark-value/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-mark-value/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-mark-value/module-trees.txtnew file+5

This diff is too big to show here.

tests/golden/module-import-api-mark-value/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-mark-value/modules/ui/api/demo.jibbnew file+3

This diff is too big to show here.

tests/golden/module-import-api-mark-value/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-mark-value/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-mark-value/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-mark-value/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-nested-path/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-nested-path/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-nested-path/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-nested-path/module-trees.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-nested-path/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-nested-path/modules/ui/api/foo/bar.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-nested-path/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-nested-path/tokens.txtnew file+15

This diff is too big to show here.

tests/golden/module-import-api-nested-path/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-nested-path/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/mar/other.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/marks.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/module-trees.txtnew file+7

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/modules/ui/api/demo.jibbnew file+5

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-paths-mark-value/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/module-trees.txtnew file+6

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/modules/ui/api/demo.jibbnew file+3

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-paths-scope-conflict/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/module-trees.txtnew file+5

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/modules/ui/api/demo.jibbnew file+3

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-poke-clash/types.txtnew file+8

This diff is too big to show here.

tests/golden/module-import-api-poke-reason/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-poke-reason/module-trees.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-poke-reason/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-poke-reason/modules/ui/api/demo.jibbnew file+1

This diff is too big to show here.

tests/golden/module-import-api-poke-reason/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-poke-reason/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-poke-reason/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-poke-reason/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-request-reason/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-request-reason/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-request-reason/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-request-reason/module-trees.txtnew file+7

This diff is too big to show here.

tests/golden/module-import-api-request-reason/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-request-reason/modules/ui/api/demo.jibbnew file+4

This diff is too big to show here.

tests/golden/module-import-api-request-reason/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-request-reason/tokens.txtnew file+21

This diff is too big to show here.

tests/golden/module-import-api-request-reason/tree.txtnew file+9

This diff is too big to show here.

tests/golden/module-import-api-request-reason/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/mar/full.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/marks.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/module-trees.txtnew file+11

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/modules.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/modules/ui/api/demo.jibbnew file+3

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/modules/ui/lib.jibbnew file+1

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-api-scope-conflict/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-import-root-import-shadow/mar/label.txtmode 100644 → 120000+1−5

This diff is too big to show here.

tests/golden/module-import-store-derived-clash/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-store-derived-clash/module-trees.txtnew file+40

This diff is too big to show here.

tests/golden/module-import-store-derived-clash/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-store-derived-clash/modules/ui/stores/cart.jibbnew file+12

This diff is too big to show here.

tests/golden/module-import-store-derived-clash/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-store-derived-clash/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-store-derived-clash/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-store-derived-clash/types.txtnew file+8

This diff is too big to show here.

tests/golden/module-import-store-face-clash/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-import-store-face-clash/module-trees.txtnew file+40

This diff is too big to show here.

tests/golden/module-import-store-face-clash/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-import-store-face-clash/modules/ui/stores/cart.jibbnew file+12

This diff is too big to show here.

tests/golden/module-import-store-face-clash/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-import-store-face-clash/tokens.txtnew file+13

This diff is too big to show here.

tests/golden/module-import-store-face-clash/tree.txtnew file+3

This diff is too big to show here.

tests/golden/module-import-store-face-clash/types.txtnew file+8

This diff is too big to show here.

tests/golden/module-import-sur-scope/types.txt+1−1

This diff is too big to show here.

tests/golden/module-missing-value-cycle/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-missing-value-cycle/module-trees.txtnew file+21

This diff is too big to show here.

tests/golden/module-missing-value-cycle/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-missing-value-cycle/modules/ui/lib.jibbnew file+4

This diff is too big to show here.

tests/golden/module-missing-value-cycle/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-missing-value-cycle/tokens.txtnew file+14

This diff is too big to show here.

tests/golden/module-missing-value-cycle/tree.txtnew file+5

This diff is too big to show here.

tests/golden/module-missing-value-cycle/types.txtnew file+2

This diff is too big to show here.

tests/golden/module-missing-value-sample-shadow/about.txtnew file+4

This diff is too big to show here.

tests/golden/module-missing-value-sample-shadow/module-trees.txtnew file+15

This diff is too big to show here.

tests/golden/module-missing-value-sample-shadow/modules.txtnew file+1

This diff is too big to show here.

tests/golden/module-missing-value-sample-shadow/modules/ui/lib.jibbnew file+3

This diff is too big to show here.

tests/golden/module-missing-value-sample-shadow/source.jibbnew file+2

This diff is too big to show here.

tests/golden/module-missing-value-sample-shadow/tokens.txtnew file+14

This diff is too big to show here.

tests/golden/module-missing-value-sample-shadow/tree.txtnew file+5

This diff is too big to show here.

tests/golden/module-missing-value-sample-shadow/types.txtnew file+4

This diff is too big to show here.

tests/golden/prelude-unit-list-transforms/types.txt+1−1

This diff is too big to show here.

tests/golden/types-cell-branch-context/types.txt+1−1

This diff is too big to show here.

tests/golden/types-change-overlap-lines/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-change-overlap-lines/modules.txtnew file+1

This diff is too big to show here.

tests/golden/types-change-overlap-lines/source.jibbnew file+7

This diff is too big to show here.

tests/golden/types-change-overlap-lines/tokens.txtnew file+49

This diff is too big to show here.

tests/golden/types-change-overlap-lines/tree.txtnew file+18

This diff is too big to show here.

tests/golden/types-change-overlap-lines/types.txtnew file+8

This diff is too big to show here.

tests/golden/types-change-overlap/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-change-overlap/modules.txtnew file+1

This diff is too big to show here.

tests/golden/types-change-overlap/source.jibbnew file+4

This diff is too big to show here.

tests/golden/types-change-overlap/tokens.txtnew file+57

This diff is too big to show here.

tests/golden/types-change-overlap/tree.txtnew file+22

This diff is too big to show here.

tests/golden/types-change-overlap/types.txtnew file+8

This diff is too big to show here.

tests/golden/types-change-repeated-wing/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-change-repeated-wing/modules.txtnew file+1

This diff is too big to show here.

tests/golden/types-change-repeated-wing/source.jibbnew file+3

This diff is too big to show here.

tests/golden/types-change-repeated-wing/tokens.txtnew file+41

This diff is too big to show here.

tests/golden/types-change-repeated-wing/tree.txtnew file+16

This diff is too big to show here.

tests/golden/types-change-repeated-wing/types.txtnew file+8

This diff is too big to show here.

tests/golden/types-change-repeated/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-change-repeated/modules.txtnew file+1

This diff is too big to show here.

tests/golden/types-change-repeated/source.jibbnew file+2

This diff is too big to show here.

tests/golden/types-change-repeated/tokens.txtnew file+39

This diff is too big to show here.

tests/golden/types-change-repeated/tree.txtnew file+15

This diff is too big to show here.

tests/golden/types-change-repeated/types.txtnew file+8

This diff is too big to show here.

tests/golden/types-change-wing/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-change-wing/modules.txtnew file+1

This diff is too big to show here.

tests/golden/types-change-wing/source.jibbnew file+24

This diff is too big to show here.

tests/golden/types-change-wing/tokens.txtnew file+289

This diff is too big to show here.

tests/golden/types-change-wing/tree.txtnew file+111

This diff is too big to show here.

tests/golden/types-change-wing/types.txtnew file+46

This diff is too big to show here.

tests/golden/types-constructor-context/types.txt+2−2

This diff is too big to show here.

tests/golden/types-generic-union-alias-face/types.txt+1−1

This diff is too big to show here.

tests/golden/types-generic-union-alias/types.txt+1−1

This diff is too big to show here.

tests/golden/types-generic-union-local/types.txt+1−1

This diff is too big to show here.

tests/golden/types-hole-module-boundary/types.txt+1−1

This diff is too big to show here.

tests/golden/types-import-mark/mar/label.txtmode 100644 → 120000+1−5

This diff is too big to show here.

tests/golden/types-list-open-constraints/about.txt+1−1

This diff is too big to show here.

tests/golden/types-list-open-constraints/types.txt+4−1

This diff is too big to show here.

tests/golden/types-list-patterns/about.txt+1−1

This diff is too big to show here.

tests/golden/types-list-patterns/source.jibb+4

This diff is too big to show here.

tests/golden/types-list-patterns/tokens.txt+241−215

This diff is too big to show here.

tests/golden/types-list-patterns/tree.txt+121−110

This diff is too big to show here.

tests/golden/types-list-patterns/types.txt+1

This diff is too big to show here.

tests/golden/types-local-capitals/about.txt+1−1

This diff is too big to show here.

tests/golden/types-local-capitals/types.txt+7−1

This diff is too big to show here.

tests/golden/types-local-error-call/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-local-error-call/source.jibbnew file+27

This diff is too big to show here.

tests/golden/types-local-error-call/tokens.txtnew file+171

This diff is too big to show here.

tests/golden/types-local-error-call/tree.txtnew file+82

This diff is too big to show here.

tests/golden/types-local-error-call/types.txtnew file+33

This diff is too big to show here.

tests/golden/types-local-error-cast/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-local-error-cast/source.jibbnew file+56

This diff is too big to show here.

tests/golden/types-local-error-cast/tokens.txtnew file+339

This diff is too big to show here.

tests/golden/types-local-error-cast/tree.txtnew file+151

This diff is too big to show here.

tests/golden/types-local-error-cast/types.txtnew file+54

This diff is too big to show here.

tests/golden/types-local-error-forward/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-local-error-forward/source.jibbnew file+26

This diff is too big to show here.

tests/golden/types-local-error-forward/tokens.txtnew file+157

This diff is too big to show here.

tests/golden/types-local-error-forward/tree.txtnew file+69

This diff is too big to show here.

tests/golden/types-local-error-forward/types.txtnew file+8

This diff is too big to show here.

tests/golden/types-local-error-order/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-local-error-order/source.jibbnew file+80

This diff is too big to show here.

tests/golden/types-local-error-order/tokens.txtnew file+588

This diff is too big to show here.

tests/golden/types-local-error-order/tree.txtnew file+269

This diff is too big to show here.

tests/golden/types-local-error-order/types.txtnew file+12

This diff is too big to show here.

tests/golden/types-local-recursive/about.txt+1−1

This diff is too big to show here.

tests/golden/types-local-recursive/types.txt+15−3

This diff is too big to show here.

tests/golden/types-many-variables/about.txtnew file+4

This diff is too big to show here.

tests/golden/types-many-variables/source.jibbnew file+6

This diff is too big to show here.

tests/golden/types-many-variables/tokens.txtnew file+266

This diff is too big to show here.

tests/golden/types-many-variables/tree.txtnew file+26

This diff is too big to show here.

tests/golden/types-many-variables/types.txtnew file+13

This diff is too big to show here.

tests/golden/types-module-fixtures/modules/ui/api/blog.jibbmode 100644 → 120000+1−5

This diff is too big to show here.

tests/golden/types-module-fixtures/modules/ui/components/card.jibbmode 100644 → 120000+1−5

This diff is too big to show here.

tests/golden/types-module-fixtures/source.jibbmode 100644 → 120000+1−9

This diff is too big to show here.

tests/golden/types-module-fixtures/types.txt+1−1

This diff is too big to show here.

tests/golden/types-module-mixed/mar/label.txtmode 100644 → 120000+1−5

This diff is too big to show here.

tests/golden/types-partial-aura-generalization/source.jibb+1−1

This diff is too big to show here.

tests/golden/types-partial-aura-generalization/tokens.txt+8−8

This diff is too big to show here.

tests/golden/types-partial-aura-generalization/tree.txt+5−5

This diff is too big to show here.

tests/golden/types-partial-aura-generalization/types.txt+1−1

This diff is too big to show here.

tests/golden/types-partial-aura/source.jibb+1−1

This diff is too big to show here.

tests/golden/types-partial-aura/tokens.txt+2−2

This diff is too big to show here.

tests/golden/types-partial-aura/tree.txt+1−1

This diff is too big to show here.

tests/golden/types-partial-aura/types.txt+1−1

This diff is too big to show here.

tests/golden/types-partial-branch-widening/about.txt+1−1

This diff is too big to show here.

tests/golden/types-partial-branch-widening/source.jibb+55

This diff is too big to show here.

tests/golden/types-partial-branch-widening/tokens.txt+358−18

This diff is too big to show here.

tests/golden/types-partial-branch-widening/tree.txt+164−14

This diff is too big to show here.

tests/golden/types-partial-branch-widening/types.txt+16−3

This diff is too big to show here.

tests/golden/types-partial-forward/about.txt+1−1

This diff is too big to show here.

tests/golden/types-partial-forward/source.jibb+3−1

This diff is too big to show here.

tests/golden/types-partial-forward/tokens.txt+10−2

This diff is too big to show here.

tests/golden/types-partial-forward/tree.txt+3−1

This diff is too big to show here.

tests/golden/types-partial-forward/types.txt+2

This diff is too big to show here.

tests/golden/types-prelude-arithmetic/about.txt+1−1

This diff is too big to show here.

tests/golden/types-prelude-arithmetic/types.txt+7−1

This diff is too big to show here.

tests/golden/types-prelude-generic-alias/types.txt+1−1

This diff is too big to show here.

tests/golden/types-prelude-lead-late/types.txt+1−1

This diff is too big to show here.

tests/golden/types-prelude-like/source.jibb+1−1

This diff is too big to show here.

tests/golden/types-prelude-like/tokens.txt+7−7

This diff is too big to show here.

tests/golden/types-prelude-like/tree.txt+2−1

This diff is too big to show here.

tests/golden/types-prelude-list-functions/types.txt+1−1

This diff is too big to show here.

tests/golden/types-prelude-sub/types.txt+1−1

This diff is too big to show here.

tests/golden/types-prelude-ui/types.txt+21−21

This diff is too big to show here.

tests/golden/types-proj-explicit-context/types.txt+2−2

This diff is too big to show here.

tests/golden/types-proj-nested-no-implicit/types.txt+3−3

This diff is too big to show here.

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

This diff is too big to show here.

tests/golden/types-record-change-generic/source.jibb−1

This diff is too big to show here.

tests/golden/types-record-change-generic/tokens.txt+35−59

This diff is too big to show here.

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-recursion-scc-import-bad/types.txt+1−1

This diff is too big to show here.

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

This diff is too big to show here.

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

This diff is too big to show here.

tests/golden/types-recursive-branch/types.txt+4−4

This diff is too big to show here.

tests/golden/types-recursive-gate/types.txt+2−2

This diff is too big to show here.

tests/golden/types-request-normal/mar/full.txtmode 100644 → 120000+1−5

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/golden/types-union-finite-generic/about.txt+1−1

This diff is too big to show here.

tests/golden/types-union-finite-generic/types.txt+7−1

This diff is too big to show here.

tests/golden/types-union-finite/about.txt+1−1

This diff is too big to show here.

tests/golden/types-union-finite/source.jibb+7

This diff is too big to show here.

tests/golden/types-union-finite/tokens.txt+210−163

This diff is too big to show here.

tests/golden/types-union-finite/tree.txt+99−78

This diff is too big to show here.

tests/golden/types-union-finite/types.txt+3−2

This diff is too big to show here.

tests/golden/types-union-patterns-generic/about.txt+1−1

This diff is too big to show here.

tests/golden/types-union-patterns-generic/types.txt+7−1

This diff is too big to show here.

tests/importer/about.txt+5−1

This diff is too big to show here.

tests/lib/jibb-api-evidence.hoon+12−6

This diff is too big to show here.

tests/lib/jibb-api-paths.hoon+18−8

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-bridge.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-buttons.hoon+1−1

This diff is too big to show here.

tests/lib/jibb-check-spans.hoonnew file+8

This diff is too big to show here.

tests/lib/jibb-deferred-context.hoon+6−2

This diff is too big to show here.

tests/lib/jibb-deferred-resolver.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-deferred.hoon+18−9

This diff is too big to show here.

tests/lib/jibb-direct-gate-source.hoon+5−1

This diff is too big to show here.

tests/lib/jibb-doc-examples.hoon+12−6

This diff is too big to show here.

tests/lib/jibb-empty.hoon+4−2

This diff is too big to show here.

tests/lib/jibb-full-overlap-basic.hoon+66−16

This diff is too big to show here.

tests/lib/jibb-full-overlap-graph.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-gate-free-source.hoon+17−8

This diff is too big to show here.

tests/lib/jibb-generic-construction.hoon+4−2

This diff is too big to show here.

tests/lib/jibb-generic-pattern.hoon+4−2

This diff is too big to show here.

tests/lib/jibb-generic-recursion.hoon+13−10

This diff is too big to show here.

tests/lib/jibb-hoon-reference.hoonnew file+60

This diff is too big to show here.

tests/lib/jibb-import-default.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-import-diagnostic.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-import-overlap.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-import-structural.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-import.hoon+571−3

This diff is too big to show here.

tests/lib/jibb-list-alias-guards.hoon+5−1

This diff is too big to show here.

tests/lib/jibb-mark-bridge.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-module-scope.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-page-main.hoon+21−15

This diff is too big to show here.

tests/lib/jibb-poke-bridge.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-program-init.hoon+33−5

This diff is too big to show here.

tests/lib/jibb-program-update.hoon+1−1

This diff is too big to show here.

tests/lib/jibb-program-watch.hoon+13−7

This diff is too big to show here.

tests/lib/jibb-proj-guards.hoon+1−1

This diff is too big to show here.

tests/lib/jibb-store.hoon+6−3

This diff is too big to show here.

tests/lib/jibb-theme.hoon+1−1

This diff is too big to show here.

tests/lib/jibb-tlon-bridge.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-todo-api.hoon+19−7

This diff is too big to show here.

tests/lib/jibb-todo-full.hoon+24−15

This diff is too big to show here.

tests/lib/jibb-todo-partial.hoon+18−9

This diff is too big to show here.

tests/lib/jibb-typecheck.hoon+7−5

This diff is too big to show here.

tests/lib/jibb-union-alias-overlap.hoon+4−1

This diff is too big to show here.

tests/lib/jibb-union-source.hoon+4−1

This diff is too big to show here.

tests/lib/jibb.hoondeleted−4000

This diff is too big to show here.

tests/type-api-evidence/expected.txtdeleted−1

This diff is too big to show here.

tests/type-api-paths/about.txt+1−1

This diff is too big to show here.

tests/type-api-paths/api.txtdeleted−13

This diff is too big to show here.

tests/type-api-paths/expected.txt+14−2

This diff is too big to show here.

tests/type-api-paths/todo-action.txtdeleted−6

This diff is too big to show here.

tests/type-api-paths/todo-item.txtdeleted−6

This diff is too big to show here.

tests/type-api-paths/todo-sur.txtdeleted−12

This diff is too big to show here.

tests/type-api-paths/todo-update.txtdeleted−6

This diff is too big to show here.

tests/type-api-paths/todos.txtdeleted−6

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-deferred/expected.txt+3−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-full-overlap/about.txt+1−1

This diff is too big to show here.

tests/type-full-overlap/atoms.txtnew file+4

This diff is too big to show here.

tests/type-full-overlap/expected-basic.txt+7

This diff is too big to show here.

tests/type-full-overlap/flag.txtnew file+4

This diff is too big to show here.

tests/type-full-overlap/nested.txtnew file+4

This diff is too big to show here.

tests/type-full-overlap/order.txtnew file+7

This diff is too big to show here.

tests/type-gate-free/about.txt+1−1

This diff is too big to show here.

tests/type-gate-free/todo.txtdeleted−40

This diff is too big to show here.

tests/type-page-main/about.txt+1−1

This diff is too big to show here.

tests/type-page-main/blog-api.txtdeleted−5

This diff is too big to show here.

tests/type-page-main/blog-index.txtdeleted−9

This diff is too big to show here.

tests/type-page-main/blog-sur.txtdeleted−6

This diff is too big to show here.

tests/type-page-main/card.txtdeleted−5

This diff is too big to show here.

tests/type-page-main/index.txtdeleted−10

This diff is too big to show here.

tests/type-page-main/posts-mark.txtdeleted−6

This diff is too big to show here.

tests/type-page-main/static.txtdeleted−7

This diff is too big to show here.

tests/type-page-main/todo-api.txtdeleted−13

This diff is too big to show here.

tests/type-page-main/todo-island.txtdeleted−40

This diff is too big to show here.

tests/type-poke/about.txt+5−2

This diff is too big to show here.

tests/type-poke/expected.txt+11−5

This diff is too big to show here.

tests/type-poke/mark.txtmode 100644 → 120000+1−5

This diff is too big to show here.

tests/type-program-main/about.txt+1−1

This diff is too big to show here.

tests/type-program-main/initializer-alias.txtnew file+11

This diff is too big to show here.

tests/type-program-main/initializer-nested-branch.txtnew file+24

This diff is too big to show here.

tests/type-program-main/initializer-open-update.txtnew file+10

This diff is too big to show here.

tests/type-program-main/initializer-open-view.txtnew file+11

This diff is too big to show here.

tests/type-program-main/initializer-pun.txtnew file+11

This diff is too big to show here.

tests/type-store/basket.txtdeleted−32

This diff is too big to show here.

tests/type-theme/source.txtdeleted−8

This diff is too big to show here.

tests/type-todo-api/about.txt+1−1

This diff is too big to show here.

tests/type-todo-full/about.txt+2−2

This diff is too big to show here.

tests/type-todo-full/cast-init.txt+2−2

This diff is too big to show here.

tests/type-todo-partial/about.txt+1−1

This diff is too big to show here.

tools/check+22−91

This diff is too big to show here.

tools/clay-fixtures+75−221

This diff is too big to show here.

tools/hoon+8−2

This diff is too big to show here.

tools/importer-testdeleted−37

This diff is too big to show here.

tools/ship+57−12

This diff is too big to show here.

tools/test-armsnew file+504

This diff is too big to show here.

tools/testdata/clay-fixtures-selftestdeleted−111

This diff is too big to show here.

tools/testdata/lead-late-hoon-reference.hoondeleted−24

This diff is too big to show here.

tools/testdata/selftest+112−3

This diff is too big to show here.

tools/testdata/ship-selftest+41−14

This diff is too big to show here.

tools/testdata/stub.hoon+4−1

This diff is too big to show here.

tools/testdata/succ-hoon-reference.hoondeleted−9

This diff is too big to show here.

tools/testdata/zing-hoon-reference.hoondeleted−17

This diff is too big to show here.

tools/type-api-evidence-testdeleted−40

This diff is too big to show here.

tools/type-api-paths-testdeleted−52

This diff is too big to show here.

tools/type-arithmetic-guards-testdeleted−28

This diff is too big to show here.

tools/type-ask-guards-testdeleted−31

This diff is too big to show here.

tools/type-buttons-testdeleted−40

This diff is too big to show here.

tools/type-cell-branch-testdeleted−43

This diff is too big to show here.

tools/type-closed-gate-guards-testdeleted−29

This diff is too big to show here.

tools/type-constructor-fit-guards-testdeleted−29

This diff is too big to show here.

tools/type-deferred-context-testdeleted−31

This diff is too big to show here.

tools/type-deferred-prepared-testdeleted−49

This diff is too big to show here.

tools/type-deferred-resolver-testdeleted−33

This diff is too big to show here.

tools/type-deferred-testdeleted−32

This diff is too big to show here.

tools/type-direct-gate-testdeleted−64

This diff is too big to show here.

tools/type-doc-examples-testdeleted−49

This diff is too big to show here.

tools/type-empty-testdeleted−55

This diff is too big to show here.

tools/type-full-overlap-testdeleted−49

This diff is too big to show here.

tools/type-gate-free-guards-testdeleted−29

This diff is too big to show here.

tools/type-gate-free-source-testdeleted−50

This diff is too big to show here.

tools/type-generic-alias-testdeleted−28

This diff is too big to show here.

tools/type-generic-construction-testdeleted−49

This diff is too big to show here.

tools/type-generic-pattern-testdeleted−52

This diff is too big to show here.

tools/type-generic-recursion-testdeleted−61

This diff is too big to show here.

tools/type-hole-guards-testdeleted−32

This diff is too big to show here.

tools/type-import-default-testdeleted−38

This diff is too big to show here.

tools/type-import-diagnostic-testdeleted−43

This diff is too big to show here.

tools/type-import-overlap-testdeleted−33

This diff is too big to show here.

tools/type-import-structural-testdeleted−36

This diff is too big to show here.

tools/type-import-testdeleted−39

This diff is too big to show here.

tools/type-list-alias-testdeleted−33

This diff is too big to show here.

tools/type-mark-testdeleted−35

This diff is too big to show here.

tools/type-module-scope-testdeleted−40

This diff is too big to show here.

tools/type-nested-union-guards-testdeleted−29

This diff is too big to show here.

tools/type-page-main-testdeleted−86

This diff is too big to show here.

tools/type-poke-testdeleted−50

This diff is too big to show here.

tools/type-positional-face-guards-testdeleted−29

This diff is too big to show here.

tools/type-program-init-testdeleted−49

This diff is too big to show here.

tools/type-program-main-testdeleted−46

This diff is too big to show here.

tools/type-program-update-testdeleted−46

This diff is too big to show here.

tools/type-program-watch-testdeleted−48

This diff is too big to show here.

tools/type-proj-guards-testdeleted−32

This diff is too big to show here.

tools/type-qath-guards-testdeleted−31

This diff is too big to show here.

tools/type-request-guards-testdeleted−31

This diff is too big to show here.

tools/type-store-testdeleted−41

This diff is too big to show here.

tools/type-sub-guards-testdeleted−31

This diff is too big to show here.

tools/type-theme-testdeleted−44

This diff is too big to show here.

tools/type-tlon-testdeleted−39

This diff is too big to show here.

tools/type-todo-api-testdeleted−62

This diff is too big to show here.

tools/type-todo-full-testdeleted−105

This diff is too big to show here.

tools/type-todo-partial-testdeleted−55

This diff is too big to show here.

tools/type-union-alias-overlap-testdeleted−52

This diff is too big to show here.

tools/type-union-source-testdeleted−55

This diff is too big to show here.

tools/urbit_eval.py+12−6

This diff is too big to show here.

vendor/LICENSE-urbit.txtnew file+21

This diff is too big to show here.

vendor/SOURCES.txt+3−1

This diff is too big to show here.