plum
git clone https://git.pyrossh.dev/plum
A statically typed, imperative programming language inspired by rust, python
42452f8
— Peter John
2026-11-04T15:48:01+05:30
docs: compiler cleanup phase 1 plan; explicit function generics queued after phase 2
docs/backlog.md
CHANGED
|
@@ -4,7 +4,8 @@ Open work, in the order the user queued it, plus smaller items found during buil
|
|
|
4
4
|
|
|
5
5
|
## Planned (in order)
|
|
6
6
|
|
|
7
|
-
1. **Compiler cleanup and architecture** — `docs/plans/2026-11-04-compiler-cleanup.review.md` (written in another session; meant to run after language-restrictions merged).
|
|
7
|
+
1. **Compiler cleanup and architecture** — `docs/plans/2026-11-04-compiler-cleanup.review.md` (written in another session; meant to run after language-restrictions merged). Approved 2026-11-04; running on branch `superlite/compiler-cleanup`, phase 1 first.
|
|
8
|
+
- **Explicit function generics** (user 2026-11-04: right after cleanup phase 2) — functions declare their generics (`fun map[B](...)`) instead of every single capital letter being a generic; allows longer generic names and one-letter concrete types/tags. Grammar change + about 140 signatures in std/examples. Phase 2's "generics by scope" makes this mostly a grammar + signature rewrite.
|
|
8
9
|
2. **Native inline variants, then decide union enums** — compile inline variants directly as struct subtypes of their enum and delete the hidden-record lowering (`hoistInlineVariants`, the `List__Cons(Cons(..))` wrappers, union forwarders). Then decide whether user-facing union enums (`enum X = A | B` of records) stay as a thin feature or fold into traits; if they go, `JsonParse` in `plum-std/Json.plum` becomes inline variants and the union examples (`unions.plum`, `struct_union_members.plum`) are rewritten. `unboxed_variants.plum` is really a compiler probe: move it to a codegen test. (Decision record §8b.)
|
|
9
10
|
3. **Benchmark** before FBIP (user: FBIP waits for it).
|
|
10
11
|
4. **FBIP: no heap mutation** — persistent std collections updated in place when unique, Koka-style `fip` functions as a checked in-place guarantee, a reference count used only as a uniqueness check if static proof falls short. Worklist = the `mut` fields left today (see below). (Decision record §9.)
|
docs/plans/2026-11-04-compiler-cleanup-phase1.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Compiler cleanup, phase 1: deletions and test helpers
|
|
2
|
+
|
|
3
|
+
**Review plan:** docs/plans/2026-11-04-compiler-cleanup.review.md
|
|
4
|
+
**Goal:** Delete dead code and small duplicates in the compiler; one shared test-support crate; fewer, de-duplicated test binaries. No behaviour change: every example compiles to byte-identical wasm.
|
|
5
|
+
**Architecture:** Rust workspace (plum-core parser+passes, plum-checker, plum-wasm-codegen, plum-cli, plum-lsp). New workspace member `plum-test-support` (dev-dependency only).
|
|
6
|
+
**Tech stack:** Rust 2021, cargo, wasmtime (GC + function references + tail calls), tree-sitter-plum.
|
|
7
|
+
**Detail:** contracts
|
|
8
|
+
**Target-min:** 14
|
|
9
|
+
|
|
10
|
+
## Global constraints
|
|
11
|
+
- Language: Rust. Test command per crate: `cargo test -p <crate>` (do NOT trust `run_tests --fast` path filters in this repo; run the crate's tests directly). Full: `cargo test --workspace`.
|
|
12
|
+
- `touch` an edited .rs file before trusting a cargo result (stale-build gotcha in this sandbox).
|
|
13
|
+
- Functions are camelCase (`#![allow(non_snake_case)]` at crate/test top), matching the repo.
|
|
14
|
+
- No behaviour change. No test may be deleted unless this plan names it.
|
|
15
|
+
- `plum-game` and `plum-runtime` are not workspace members: out of scope this phase.
|
|
16
|
+
- Never run `plum format` on real files (it rewrites in place).
|
|
17
|
+
|
|
18
|
+
## Main diagram
|
|
19
|
+
```mermaid
|
|
20
|
+
flowchart LR
|
|
21
|
+
TS["plum-test-support"] --> CT["checker tests"]
|
|
22
|
+
TS --> GT["codegen tests"]
|
|
23
|
+
TS --> E2E["e2e binaries"]
|
|
24
|
+
TS --> CO["core + cli tests"]
|
|
25
|
+
DC["dead code: core / checker / codegen"] --> V["verify: suite + wasm hashes"]
|
|
26
|
+
WH["wasm-hashes script"] --> V
|
|
27
|
+
CT --> V
|
|
28
|
+
GT --> V
|
|
29
|
+
E2E --> V
|
|
30
|
+
CO --> V
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## File structure
|
|
34
|
+
- `scripts/wasm-hashes.sh` — compile every example with `main` at a git rev, print sha256 per file.
|
|
35
|
+
- `plum-test-support/{Cargo.toml,src/lib.rs}` — shared test helpers (parse, load, compile, engine, run, errors).
|
|
36
|
+
- `plum-wasm-codegen/tests/{e2e_records,e2e_types,e2e_tail,e2e_mem}/` — 4 e2e binaries replacing 19 files.
|
|
37
|
+
- `plum-checker/tests/features/` — one binary for the small checker test files.
|
|
38
|
+
|
|
39
|
+
## Task graph
|
|
40
|
+
```mermaid
|
|
41
|
+
flowchart LR
|
|
42
|
+
T1[wasm hash script]
|
|
43
|
+
T2[core dead code]
|
|
44
|
+
T3[checker duplicates]
|
|
45
|
+
T4[codegen dead code]
|
|
46
|
+
T5[test-support crate]
|
|
47
|
+
T6[checker tests]
|
|
48
|
+
T7[codegen unit tests]
|
|
49
|
+
T8[e2e records binary]
|
|
50
|
+
T12[e2e types binary]
|
|
51
|
+
T9[e2e tail binary]
|
|
52
|
+
T13[e2e memory binary]
|
|
53
|
+
T10[core and cli tests]
|
|
54
|
+
T11[verify phase 1]
|
|
55
|
+
%% taskgraph
|
|
56
|
+
T5 --> T6
|
|
57
|
+
T5 --> T7
|
|
58
|
+
T5 --> T8
|
|
59
|
+
T5 --> T9
|
|
60
|
+
T5 --> T12
|
|
61
|
+
T5 --> T13
|
|
62
|
+
T5 --> T10
|
|
63
|
+
T1 --> T11
|
|
64
|
+
T2 --> T11
|
|
65
|
+
T3 --> T11
|
|
66
|
+
T4 --> T11
|
|
67
|
+
T6 --> T11
|
|
68
|
+
T7 --> T11
|
|
69
|
+
T8 --> T11
|
|
70
|
+
T9 --> T11
|
|
71
|
+
T12 --> T11
|
|
72
|
+
T13 --> T11
|
|
73
|
+
T10 --> T11
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Package A: compiler deletions
|
|
77
|
+
**Probe entry:** run=cargo test --workspace
|
|
78
|
+
|
|
79
|
+
### T1 wasm hash script · Complexity 3 · Est. context 25k
|
|
80
|
+
**Owns:** scripts/wasm-hashes.sh
|
|
81
|
+
**Components:** 1
|
|
82
|
+
**LOC owned:** 60
|
|
83
|
+
**Tests:** slow
|
|
84
|
+
**Kind:** design
|
|
85
|
+
**Model:** sonnet
|
|
86
|
+
**Produces:** scripts/wasm-hashes.sh REV OUT -> writes OUT with lines `<sha256> <relpath>` sorted by relpath
|
|
87
|
+
**Test code:** `bash scripts/wasm-hashes.sh HEAD /tmp/a.txt && bash scripts/wasm-hashes.sh HEAD /tmp/b.txt && diff /tmp/a.txt /tmp/b.txt` exits 0 and a.txt has ≥ 20 lines.
|
|
88
|
+
**Steps:** `git worktree add --detach $TMP REV`; `cargo build -p plum-cli` there (separate target dir under $TMP); for every `plum-examples/**/*.plum` containing `fun main`, run a fresh `plum compile <file> -o <tmp>.wasm` (one process per file, so global counters start at 0); sha256 each; print `sha relpath`; files that fail to compile print `FAIL relpath`; remove the worktree on exit (trap).
|
|
89
|
+
|
|
90
|
+
### T2 plum-core dead code · Complexity 2 · Est. context 30k
|
|
91
|
+
**Owns:** plum-core/src/drive.rs, plum-core/src/simplify.rs, plum-core/src/closure_spec.rs, plum-core/src/parser.rs, plum-core/src/uniqueness.rs
|
|
92
|
+
**Components:** 1
|
|
93
|
+
**LOC owned:** 40
|
|
94
|
+
**Tests:** fast
|
|
95
|
+
**Kind:** mechanical
|
|
96
|
+
**Model:** haiku
|
|
97
|
+
**Produces:** none
|
|
98
|
+
**Test code:** `cargo test -p plum-core` passes; `cargo build -p plum-core` prints no dead_code warning.
|
|
99
|
+
**Steps:** delete `struct Scoper` and its impl in drive.rs (≈line 2275; simplify.rs has its own used Scoper — keep that one); delete `pub fn specialise` in closure_spec.rs:22 (keep `specialiseWith`); remove `#![allow(dead_code)]` from drive.rs:11 and simplify.rs:7, then delete every item the warnings name (expected: simplify `Scoper.ctors` field, uniqueness `selfUnit`); inline `parser::forStmts` (parser.rs:903) at its call sites. Grep all crates before deleting anything `pub`.
|
|
100
|
+
|
|
101
|
+
### T3 checker duplicates · Complexity 4 · Est. context 45k
|
|
102
|
+
**Owns:** plum-checker/src/lib.rs
|
|
103
|
+
**Components:** 2
|
|
104
|
+
**LOC owned:** 90
|
|
105
|
+
**Tests:** fast
|
|
106
|
+
**Model:** sonnet
|
|
107
|
+
**Produces:** PlumType::primitiveName(&self) -> Option<&'static str> · PlumType::fromPrimitiveName(name: &str) -> Option<PlumType>
|
|
108
|
+
e.g. PlumType::TInt.primitiveName() -> Some("Int")
|
|
109
|
+
e.g. PlumType::fromPrimitiveName("Bool") -> Some(PlumType::TBool)
|
|
110
|
+
e.g. PlumType::fromPrimitiveName("Str") -> None
|
|
111
|
+
**Review Focus:** `trmc_recheck_uses_recheck_keep`: the TRMC block in `typedSource` (≈1294-1309) calls `recheckKeep` and existing trmc/fusion tests still pass; `empty_union_plan_single_check`: `checkUnions` with an empty recorded plan returns the lowered copy without a second `check(source)`, and unions_tests still pass.
|
|
112
|
+
**Test code:** unit tests in a `#[cfg(test)] mod primitive_names` inside lib.rs asserting the three e.g. lines plus round-trip for Int/Float/Bool/Byte/Unit; `cargo test -p plum-checker` passes.
|
|
113
|
+
**Steps:** add the two fns as an inherent `impl PlumType` block in lib.rs (not types.rs); replace the 7 hand-written name↔type matches (≈lines 655, 681, 715, 1387, 1879, 2157, 4823) with them where the mapping is identical (leave a site alone if it differs, e.g. extra names); replace `closureHints::head` (≈1384) with `methodReceiverName`; TRMC block → `recheckKeep`; `checkUnions` empty-plan shortcut; fix the stale `OP_CALLS` doc comment (≈45).
|
|
114
|
+
|
|
115
|
+
### T4 codegen dead code · Complexity 1 · Est. context 22k
|
|
116
|
+
**Owns:** plum-wasm-codegen/src/lib.rs
|
|
117
|
+
**Components:** 1
|
|
118
|
+
**LOC owned:** 20
|
|
119
|
+
**Tests:** fast
|
|
120
|
+
**Kind:** mechanical
|
|
121
|
+
**Model:** haiku
|
|
122
|
+
**Produces:** none
|
|
123
|
+
**Test code:** `cargo test -p plum-wasm-codegen --lib` and `cargo build --workspace` pass.
|
|
124
|
+
**Steps:** delete `WasmModule::addDataSegment` (lib.rs:137), the `DataSegmentEntry::Active` variant and its encoding branch (≈317) if nothing else constructs it (grep); remove the stale comments "Task 1" (≈156) and "Before wasm-gc" (≈4487).
|
|
125
|
+
|
|
126
|
+
## Package B: tests
|
|
127
|
+
**Probe entry:** run=cargo test --workspace
|
|
128
|
+
|
|
129
|
+
### T5 plum-test-support crate · Complexity 4 · Est. context 40k
|
|
130
|
+
**Owns:** plum-test-support/Cargo.toml, plum-test-support/src/lib.rs, Cargo.toml, plum-checker/Cargo.toml, plum-wasm-codegen/Cargo.toml, plum-core/Cargo.toml, plum-cli/Cargo.toml
|
|
131
|
+
**Components:** 1
|
|
132
|
+
**LOC owned:** 140
|
|
133
|
+
**Tests:** fast
|
|
134
|
+
**Model:** sonnet
|
|
135
|
+
**Produces:**
|
|
136
|
+
- plum_test_support::repoRoot() -> PathBuf
|
|
137
|
+
- plum_test_support::parse(src: &str) -> plum_core::ast::Source (panics with the syntax errors if the tree has_error)
|
|
138
|
+
- plum_test_support::parseRaw(src: &str) -> plum_core::ast::Source (no assert)
|
|
139
|
+
- plum_test_support::load(name: &str, src: &str) -> Result<plum_core::ast::Source, String>
|
|
140
|
+
- plum_test_support::compile(name: &str, src: &str) -> Vec<u8> (load + compileSource + validate, panics on error)
|
|
141
|
+
- plum_test_support::engine() -> wasmtime::Engine (gc, function_references, tail_call on)
|
|
142
|
+
- plum_test_support::runInt(name: &str, src: &str) -> i64
|
|
143
|
+
- plum_test_support::runStr(name: &str, src: &str) -> String
|
|
144
|
+
- plum_test_support::checkErrors(name: &str, src: &str) -> Vec<String> (load + typedSource errors; load error returned as one string)
|
|
145
|
+
- plum_test_support::PRE: &str = "import std/Str\nimport std/Int\nimport std/Float\nimport std/Slice\n\n"
|
|
146
|
+
e.g. parse("fun main() -> Int = 1").fns.len() -> 1
|
|
147
|
+
e.g. runInt("t1", &format!("{PRE}fun main() -> Int = 40 + 2")) -> 42
|
|
148
|
+
e.g. checkErrors("t2", &format!("{PRE}fun main() -> Int = True")) -> vec with one message containing "Bool"
|
|
149
|
+
**Test code:** `plum-test-support/src/lib.rs` `#[cfg(test)]` tests asserting each e.g. line, plus `parse("fun main( ->")` panics (`#[should_panic]`).
|
|
150
|
+
**Notes:** copy behaviour from `plum-wasm-codegen/tests/record_init_e2e_test.rs` (load uses a temp dir `plum_ts_<name>_<pid>` + `loadAndMerge(&path, &repoRoot())`; run uses `define_unknown_imports_as_default_values`). `runStr` reads a returned Str the way `plum-wasm-codegen/tests/examples_test.rs` does. Add the crate to workspace members, and add `plum-test-support = { path = "../plum-test-support" }` under `[dev-dependencies]` of plum-checker, plum-wasm-codegen, plum-core and plum-cli (T5 alone edits these Cargo.toml files). If the exact checker error API differs, match what `plum-checker/tests/*` already call.
|
|
151
|
+
|
|
152
|
+
### T6 checker tests · Complexity 4 · Est. context 55k
|
|
153
|
+
**Owns:** plum-checker/tests/*.rs, plum-checker/tests/features/*, plum-checker/src/types.rs
|
|
154
|
+
**Components:** 2
|
|
155
|
+
**LOC owned:** 120
|
|
156
|
+
**Tests:** fast
|
|
157
|
+
**Model:** sonnet
|
|
158
|
+
**Consumes:** plum_test_support::parse(src: &str) -> plum_core::ast::Source (T5) · plum_test_support::load(name: &str, src: &str) -> Result<plum_core::ast::Source, String> (T5) · plum_test_support::repoRoot() -> PathBuf (T5)
|
|
159
|
+
**Produces:** none
|
|
160
|
+
**Review Focus:** `sweep_recurses`: `typed_source_has_no_unresolved_infer_vars` (checker_tests.rs:315) walks plum-std and plum-examples recursively (incl. plum-std/game/* and plum-examples/games/**) and still passes — if a newly covered file fails, keep it listed in an explicit skip list with a comment and report it; `parse_asserts`: checker_tests' `parse()` now fails on syntax errors.
|
|
161
|
+
**Test code:** `cargo test -p plum-checker` passes; test count unchanged except the deleted `freshVarsAreUnique` InferState test.
|
|
162
|
+
**Steps:** replace local parse/load/repoRoot helpers; merge io_capability, primitive_generics, variant_pattern, types, pattern_casing, closure_types, optional_unpinned, mutability test files into `tests/features/main.rs` with one `mod` file each; delete `types::InferState` and its test.
|
|
163
|
+
|
|
164
|
+
### T7 codegen unit tests · Complexity 3 · Est. context 50k
|
|
165
|
+
**Owns:** plum-wasm-codegen/tests/codegen_tests.rs, plum-wasm-codegen/tests/examples_test.rs, plum-wasm-codegen/tests/fusion_alloc_test.rs
|
|
166
|
+
**Components:** 1
|
|
167
|
+
**LOC owned:** 80
|
|
168
|
+
**Tests:** slow
|
|
169
|
+
**Model:** sonnet
|
|
170
|
+
**Consumes:** plum_test_support::parse(src: &str) -> plum_core::ast::Source (T5) · plum_test_support::engine() -> wasmtime::Engine (T5) · plum_test_support::load(name: &str, src: &str) -> Result<plum_core::ast::Source, String> (T5) · plum_test_support::repoRoot() -> PathBuf (T5)
|
|
171
|
+
**Produces:** none
|
|
172
|
+
**Review Focus:** `parse_asserts`: codegen_tests' `parse()` (line 6) fails on syntax errors; any of its 16 callers that relied on a partial parse is fixed in the test source, not by `parseRaw`, and reported.
|
|
173
|
+
**Test code:** `cargo test -p plum-wasm-codegen --test codegen_tests --test examples_test --test fusion_alloc_test` passes, same test count.
|
|
174
|
+
**Steps:** replace local helpers; examples_test's examples walk recursive if it isn't already.
|
|
175
|
+
|
|
176
|
+
### T8 e2e records binary · Complexity 3 · Est. context 35k
|
|
177
|
+
**Notes:** all e2e tasks (T8, T12, T9, T13): move files to `tests/<bin>/<feature>.rs` as `mod`s of `tests/<bin>/main.rs` with the shared helpers, delete the old files; temp names unique per test; `cargo test -p plum-wasm-codegen --test <bin>`.
|
|
178
|
+
**Owns:** plum-wasm-codegen/tests/e2e_records/*, plum-wasm-codegen/tests/{empty_record_embed,enum_init,inline_variants,record_embed,record_init,unboxed_variants}_e2e_test.rs
|
|
179
|
+
**Components:** 1
|
|
180
|
+
**LOC owned:** 60
|
|
181
|
+
**Tests:** slow
|
|
182
|
+
**Model:** sonnet
|
|
183
|
+
**Consumes:** plum_test_support::runInt(name: &str, src: &str) -> i64 (T5) · plum_test_support::PRE: &str (T5)
|
|
184
|
+
**Produces:** none
|
|
185
|
+
**Test code:** `--test e2e_records` passes, same count.
|
|
186
|
+
|
|
187
|
+
### T12 e2e types binary · Complexity 3 · Est. context 35k
|
|
188
|
+
**Owns:** plum-wasm-codegen/tests/e2e_types/*, plum-wasm-codegen/tests/{traits,unions,io_entry,closure_types}_e2e_test.rs, plum-wasm-codegen/tests/type_param_static_test.rs
|
|
189
|
+
**Components:** 1
|
|
190
|
+
**LOC owned:** 60
|
|
191
|
+
**Tests:** slow
|
|
192
|
+
**Model:** sonnet
|
|
193
|
+
**Consumes:** plum_test_support::runInt(name: &str, src: &str) -> i64 (T5) · plum_test_support::compile(name: &str, src: &str) -> Vec<u8> (T5) · plum_test_support::PRE: &str (T5)
|
|
194
|
+
**Produces:** none
|
|
195
|
+
**Review Focus:** `closure_dupes`: delete closure_types `g2_never_called_is_error` and `g1_typed_param` only if their source equals checker `local_closure_never_called_error` / `typed_param_used`; else keep and report.
|
|
196
|
+
**Test code:** `--test e2e_types` passes, count minus the deleted ones.
|
|
197
|
+
|
|
198
|
+
### T9 e2e tail binary · Complexity 3 · Est. context 35k
|
|
199
|
+
**Owns:** plum-wasm-codegen/tests/e2e_tail/*, plum-wasm-codegen/tests/{closure_tail,error_tail,loop_break,tail_call,tail_calls}_e2e_test.rs
|
|
200
|
+
**Components:** 1
|
|
201
|
+
**LOC owned:** 60
|
|
202
|
+
**Tests:** slow
|
|
203
|
+
**Model:** sonnet
|
|
204
|
+
**Consumes:** plum_test_support::runInt(name: &str, src: &str) -> i64 (T5) · plum_test_support::compile(name: &str, src: &str) -> Vec<u8> (T5) · plum_test_support::PRE: &str (T5)
|
|
205
|
+
**Produces:** none
|
|
206
|
+
**Review Focus:** `tail_dedupe`: tail_call + tail_calls become one `tail` mod; delete `self_tail_call_deep`, `mutual_tail_call_deep`, `closure_tail_call`; keep `self_tail_million`, `mutual_tail_million`, `closure_tail_call_runs` and the wasm-shape tests.
|
|
207
|
+
**Test code:** `--test e2e_tail` passes, count minus 3.
|
|
208
|
+
|
|
209
|
+
### T13 e2e memory binary · Complexity 3 · Est. context 30k
|
|
210
|
+
**Owns:** plum-wasm-codegen/tests/e2e_mem/*, plum-wasm-codegen/tests/{reuse,unique_inplace,unique_spread}_e2e_test.rs
|
|
211
|
+
**Components:** 1
|
|
212
|
+
**LOC owned:** 50
|
|
213
|
+
**Tests:** slow
|
|
214
|
+
**Model:** sonnet
|
|
215
|
+
**Consumes:** plum_test_support::runInt(name: &str, src: &str) -> i64 (T5) · plum_test_support::compile(name: &str, src: &str) -> Vec<u8> (T5) · plum_test_support::PRE: &str (T5)
|
|
216
|
+
**Produces:** none
|
|
217
|
+
**Test code:** `--test e2e_mem` passes, same count.
|
|
218
|
+
|
|
219
|
+
### T10 core and cli tests · Complexity 3 · Est. context 45k
|
|
220
|
+
**Owns:** plum-core/tests/*.rs, plum-cli/tests/*.rs
|
|
221
|
+
**Components:** 1
|
|
222
|
+
**LOC owned:** 100
|
|
223
|
+
**Tests:** fast
|
|
224
|
+
**Model:** sonnet
|
|
225
|
+
**Consumes:** plum_test_support::parse(src: &str) -> plum_core::ast::Source (T5) · plum_test_support::repoRoot() -> PathBuf (T5)
|
|
226
|
+
**Produces:** none
|
|
227
|
+
**Test code:** `cargo test -p plum-core` and `cargo test -p plum-cli` pass, same counts.
|
|
228
|
+
**Notes:** plum-core dev-depending on plum-test-support is a dev-dependency cycle. If it causes `ast::Source` type mismatches (then remove nothing from Cargo.toml; just don't use it), keep plum-core's local parse helpers but make every one assert `!tree.root_node().has_error()`, and report it. plum-cli tests: use the support crate only where they hand-roll the same helpers.
|
|
229
|
+
|
|
230
|
+
## Package C: verify
|
|
231
|
+
**Probe entry:** run=bash scripts/wasm-hashes.sh
|
|
232
|
+
|
|
233
|
+
### T11 verify phase 1 · Complexity 2 · Est. context 30k
|
|
234
|
+
**Owns:** docs/plans/2026-11-04-compiler-cleanup-phase1.results.md
|
|
235
|
+
**Components:** 1
|
|
236
|
+
**LOC owned:** 40
|
|
237
|
+
**Tests:** slow
|
|
238
|
+
**Model:** sonnet
|
|
239
|
+
**Consumes:** scripts/wasm-hashes.sh REV OUT -> writes OUT with lines `<sha256> <relpath>` sorted by relpath (T1)
|
|
240
|
+
**Produces:** none
|
|
241
|
+
**Review Focus:** `wasm_identical`: hashes at the start sha (`.superlite/progress.md`) equal hashes of the current tree (`git stash create` gives a sha; commit nothing).
|
|
242
|
+
**Test code:** `cargo test --workspace` green; hash diff empty.
|
|
243
|
+
**Steps:** results file: hash diff, workspace test totals, Rust LOC, test-binary count, `#[test]` count, each before/after.
|
|
244
|
+
|
|
245
|
+
## Review Focus
|
|
246
|
+
- Package A (library/compiler): deep, state — risk: deleting something only used via another crate; the checkUnions shortcut changing which errors surface.
|
|
247
|
+
- Package B (test harness): file, state — risks: temp-dir name collisions between merged tests (name must stay unique per test), test count silently dropping, dev-dep cycle.
|
|
248
|
+
- Package C: file — wasm output must be identical.
|
|
249
|
+
|
|
250
|
+
## Self-review
|
|
251
|
+
Coverage: every phase-1 row of the review plan maps to T2–T13. Scope rulings are in `.superlite/progress.md`.
|