Exercise both real drivers with an earlier single-file decoy and a later canonical package directory, exact sorted unit ownership, direct export composition, deterministic package artifacts, transitive linking, stable file-only rejection, and a directory-package test import.
Build w6a and w6l from package-main directories and expose the wcc backend through a narrow package API so w6c and wwdump no longer import implementation files. Retarget the remaining load-bearing fixtures and example sources to directory packages; retain the one intentional flat compiler collision as an explicitly composed raw unit.
The TODO(#11) silent-accept of `for (let (a, a) .. xs)` rested on a
stale premise -- resolvewalk has per-block scopes since #53 and IS
the live w6c_ww checker pass. Bindings now install in a per-LOOP
scope (the N_MCASE pattern), so a duplicate name within one pattern
errs "redeclared in same scope" (cstage parity via stamptuplebinds'
scopedefine-nil check) while sequential same-name loops stay legal.
kwtab restores its stated alphabetical order (`import` before `is`,
both stages, kinds swapped in lockstep with names).
Four seams from one review cluster, all landing on the same checker
files; gates ran on the union (rule 11 body).
?-subset: the wwstage walk compared `...spread` ALIAS nodes on both
sides of the error-subset check, falsely rejecting a spread-carried
error return (`(i64 | ...errs)`, cs-accept/ww-reject) — both sides
now flatten like trycountvariants (cstage Tparams are pre-flattened
at type level).
Multi-let/multi-assign: the tuple gates keyed on the RAW rhs kind,
rejecting a NAMED tuple alias (`type pair = (i64,i64)`; cs clean-
reject, ww asserttyped stop) — both stages chase per #99 alias
transparency, wwstage rettupleof peels the alias so cgmassign keeps
the str element's len/cap stores, and the catA massign-alias error
pin re-rules to a run fixture. The N_MLET diagnostic also printed
its operands swapped (elem/declared reversed vs its wording).
Yield: match_yield_type didn't descend into N_SWITCH, so a yield
inside a switch arm typed the match void and dropped the value
(both stages); and a stray yield outside any match arm reached cgen
unchecked — both stages now gate on a match-arm counter (the
c->loops discipline).
cstage rejects `add(1,2,3)` and `add(4)` (too many / not enough
arguments); wwstage ran no count check at this seam, so both built
-- a stray arg pushed silently, a missing one read garbage
(cs-reject/ww-accept build-verdict divergence). Surplus errs when
params exhaust with args left; missing errs on a leftover regular
param (a leftover TK_ELLIPSIS or FFI "..." is a legal zero-arg
variadic tail). fn-VALUE callees still bail at decl==nil -- their
whole typecheck, arity included, stays task #51.