Flip the soft-default to a hard "missing package clause" error symmetrically in
both stages (cmd/wcc/parse.c + lib/ww/syntax/parse.ww): the first real decl of a
primary section with empty pathmod/resetmod and no seen clause is now rejected.
Closes the documented soft-default divergence (the 63-wrapper carve-out).
The gate flip can't be split from the migration it breaks, so this is one atomic
commit: ~80 test/wcc wrappers gain `package main;` via a shared wwtestpkg.h
helper, 6 data fixtures plus 17 asm-grep assertions update for the bare->main.<leaf>
root-helper mangle shift, and rt/ declares `package rt;` with @symbol pinning the
bare rt_ensure/rt_malloc linker names.
Root mangling narrows: the executable entry `main` stays bare (existing
carve-out), but root helper symbols become main.X. The #84 cluster is rewritten
to assert main.run distinct from aa.run/test.run; its cgen fix and bare machinery
are retained — still load-bearing for package-less module-reset deps. New
table-driven test 782_strict_package.c (6 rows, both stages).
Retiring //ww:module-reset is deferred to #24b: it is load-bearing (clears the
.wwi pathmod so the body's package clause asserts), not a vestige; fusing its
removal here would be a silent mismatch.
All byte-id gates green; full make test reports "all 335 tests passed".
The driver flip moves build artifacts from next-to-source <stem>.s to a
.sepwork/ scratch dir. 29 Pattern-B gates now build `ww build --sep -o <stem>`
and read <stem>.sepwork/__root.s (multi-package gates concat all
<stem>.sepwork/*.s, since cross-package labels live in per-package .s).
All intermediates redirect to /tmp (WW_PKGCACHE + -o), so the corpus runs
parallel-safe with no source-tree pollution. Tests pass now (--sep is live)
and survive the flip.
915 additionally retargeted off strconv's PRIVATE left_shift_table (a let,
not export) — which separate compilation correctly hides — onto a test-local
package that exports its own probe table (#96). The combined path only linked
it via a single-unit private leak; encapsulation is now honored under sep.
Test-only; all 5 *_ww binaries HOLD. 989_m1mangle_run deferred (blocked by
#99, imported-package fn main mangling under sep).
cgmatch's non-nullable variant-tag synthesis gated flatvariantidx on
pat.kind == N_TNAME (with N_TSLICE else-branch for #19's untyped-elem
fallback). N_TPTR / N_TFN / N_TPTR(N_TFN) case-patterns fell through
both, leaving r=-1 → want=0 so every variant past 0 silently
collapsed to tag 0 — runtime-passes only when the value happens to
sit on variant 0 (zero-coincidence miscompile).
Cstage cg_tag_for_variant works on resolved Type and is kind-
agnostic; harec stores `_case->type = ctype` (ref/harec check.c:2527).
#66 Phase-N already flipped match dispatch to typeeq; #179 is the
last site still keyed on AST kind. Memory: project_tinfo_lossy_nominal
+ feedback "Hare = resolved-type-only match dispatch".
Route through flatvariantidxt(scrutt.type_, pat.type_) directly,
guarded by istaggedtype + typeisslice(pattype) for the slice axis.
No new helper — existing flatvariantidxt / flatslicevariantidx wire
up unchanged.
767 probe locks the fix across 5 rows: (1) nullable *fn branched
store (ken's verify gate — proves the nullable arm at line 1484
isn't perturbed); (2) *i32|*i64 storing &i64 — pre-fix wwstage
emitted CMPQ $0 for *i64 arm, post-fix CMPQ $1; (3) *fn(i32)|*fn(i64)
via intermediate local; (4) branched runtime variant choice defeats
const-fold; (5) aliased ptr variants (typeeq through TY_NAMED).
Per row: cs runtime, ww runtime, cs.s == ww.s byte-id.
Sibling filed inline: widening `&fn` INLINE into a fn-ptr-only
tagged union picks tag 0 in wwstage's cgwidentaggedstorebp
(out-of-scope; row 3 dodges via intermediate ident store).