1383 lines
87 KiB
Markdown
1383 lines
87 KiB
Markdown
# WW test architecture
|
||
|
||
Status: active architecture as of 2026-08-07. The target graph, corpus
|
||
accounting, and complete `test-commit` gate have been rechecked, including its
|
||
two concurrency controls separately and together. The separately gated
|
||
byte-identity and test-infrastructure proofs have also run. Bootstrap and
|
||
platform proofs have not run as part of this revision.
|
||
|
||
## Why the old suite was slow
|
||
|
||
The former suite made shell, Make, and one C executable per legacy case share
|
||
ownership of discovery, registration, phase selection, scheduling, result
|
||
records, timeout classification, and a last-green cache. Language behavior and
|
||
byte-identity loops repeatedly rebuilt complete package graphs. The measured
|
||
serial result was 411.403 seconds wall time, with a static lower bound of about
|
||
11,040 compiler-stage processes and 4,800 archive creations.
|
||
|
||
The replacement assigns each assertion to one owner and keeps expensive proof
|
||
categories out of the ordinary developer target.
|
||
|
||
## Owners
|
||
|
||
| Category | Owner |
|
||
| --- | --- |
|
||
| Arena, lexer, parser, checker, module-decl parse, narrow codegen | Six in-process C unit binaries |
|
||
| Compile success/rejection, stage-routed diagnostics, and runtime exit | `test/wcc/data/*/case.ww`, executed by `wwfixture` |
|
||
| Package semantics | `test/package`, `test/sep/sepinit_test.ww`, and the native package-test coordinator |
|
||
| Language behavior | `test/lang/*_test.ww` through the language `@test` runtime |
|
||
| Library behavior | The package coordinator's `lib/...` tree walk (`ww test -j N lib/...`) |
|
||
| Standalone library-source compilation | Three import-free real source paths named by `LIBRARY_STANDALONE_SOURCES`, compiled directly by both frontends |
|
||
| Compiler-output identity | `test-lang-byteid` and `test-data-byteid` plus residual byte/artifact carriers |
|
||
| Fixed point and self-host | `test-bootstrap` |
|
||
| Host linker/platform behavior | `test-platform` |
|
||
|
||
The live declarative compiler corpus has 1,759 fixtures and 3,518 C/WW cells:
|
||
351 expected rejections, 22 compile-only successes, 209 exit-zero
|
||
programs, and 1,177 explicit-exit programs.
|
||
|
||
15 native C carriers remain. They are partitioned exactly once into
|
||
the two terminal classes: six in-process units (`738_module_decl`
|
||
re-homed from the residuals — Go does not distinguish "bootstrap
|
||
observers" from unit tests, and its parsefile-call shape is exactly
|
||
the `200_parse` class), six bootstrap gates, and three platform-claim
|
||
carriers (`996_dyn_ww` under `test-platform`; `810_dyn` and
|
||
`989_dynentry_run` hold host loader/glibc claims and run with
|
||
`test-compiler`). The residual class is EMPTY: `794_xmod_ident_prefer`
|
||
— the last bug-pinned survivor — retired with its #55-sibling cgen
|
||
fix (its assertions migrated to `test/xmod/collide_test.ww`).
|
||
|
||
The 2026-08-08 residual drain retired the other 107: 5 deleted against
|
||
verified owners, 196 rows migrated into corpus fixtures (700_e2e's 136,
|
||
the fixture-class 46, the 926/929/671 run legs), and the rest ported to
|
||
ww-native observer suites on `test/testenv`, each carrier retired in
|
||
the same commit as its replacement: `test/sep/` (sep-layout/driver),
|
||
`test/xmod/` (module-tree collisions, mangle, typecheck, direnum),
|
||
`test/asm/` (positional asm-window needle observers), `test/object/`
|
||
(w6a/w6l ELF, archive, and link facts), `test/misc/` (divergence pins,
|
||
stamp probes, wwi round-trips), `test/tool/` (driver CLI, wwdump
|
||
gates, FFI, the c6 soak), and `test/libenv/` (the lib/os + lib/dirs
|
||
env-arranger legs; those lib suites now pass bare with loud SKIPs).
|
||
All suites run under `test-compiler`. The byte/artifact partition
|
||
stays EMPTY under `test/byteid/` exactly as before; wwstage-driver-leg
|
||
byte identity keeps its one owner, `test/byteid/libbyteid_test.ww`
|
||
(44-entry roster plus the lib/ completeness scan). Known cs≠ww
|
||
divergences exposed by row migration are pinned in
|
||
`DATABYTEID_DIVERGED` (3 entries) on the graduation discipline.
|
||
|
||
## Carrier endgame
|
||
|
||
The declarative corpus and the native `@test` owners are the permanent
|
||
test surface — the `go/test/` analogy. The native C carrier fleet is the
|
||
pre-Go-1.5 artifact and shrinks toward exactly two terminal classes:
|
||
|
||
1. **C-bootstrap observers.** The six in-process units watch the C
|
||
frontend from inside its own process and are irreplaceable while
|
||
`cmd/` is the live frontend. The six bootstrap gates are the same
|
||
class's proof column: they compare the wwstage tools against the C
|
||
stage to a fixed point. At the eventual selfhost flip both freeze
|
||
into a bootstrap smoke gate (Go 1.5 deleted its C toolchain and that
|
||
toolchain's tests; it did not port them).
|
||
2. **Host ABI/platform gates.** Behavior owned by the host linker,
|
||
loader, or ABI (`996_dyn_ww` today). These observe the platform, not
|
||
the compiler, and stay native exactly as long as the claim is about
|
||
the platform.
|
||
|
||
Everything else gets a ww owner. Byte and artifact observations —
|
||
assembly-pattern greps, symbol tables, frame layouts, `.wwi`
|
||
round-trips, driver-leg comparisons — are subprocess plus file IO plus
|
||
string search, which `test/package/package_test.ww` already performs
|
||
natively (runcommand + in-language assertions). A C carrier whose
|
||
assertions fit that shape is ported and retired in the same commit,
|
||
assertions preserved or strengthened, with no compatibility execution
|
||
path left behind. A carrier that is merely historical is deleted
|
||
outright; git history is the archive.
|
||
|
||
## Public targets
|
||
|
||
| Target | Composition |
|
||
| --- | --- |
|
||
| `test` | Six in-process units plus one compile-only C/WW compiler-fixture smoke case |
|
||
| `test-compiler` | Complete fixture corpus plus residual compiler/integration carriers |
|
||
| `test-package` | Package planning, grouping, routing, and package runtime only |
|
||
| `test-lang` | Language-owned `@test` behavior |
|
||
| `test-library` | The coordinator's `lib/...` walk plus three import-free standalone-source C/WW compilation checks |
|
||
| `test-commit` | Unit + compiler + package + language + library behavior |
|
||
| `test-byteid` | Compiler-output identity gates |
|
||
| `test-bootstrap` | Fixed-point bootstrap plus the 950/991–995 native gates |
|
||
| `test-platform` | Host-dependent dynamic-link gate |
|
||
| `test-wwfixture` | Fixture CLI/process/protocol integration boundary |
|
||
| `test-all` | Commit + byte-ID + bootstrap + platform + test-infrastructure checks |
|
||
|
||
`test-commit` deliberately excludes byte identity, bootstrap, and platform
|
||
work. `test` is intentionally smaller than the old target and is the ordinary
|
||
developer feedback gate. Its purpose is a short, direct path from a compiler
|
||
edit to useful evidence, not compliance with an arbitrary wall-clock cutoff.
|
||
|
||
Make and fixture scheduling have separate, explicit owners. The Makefile does
|
||
not detect CPU count or add `-j` to `MAKEFLAGS`; the caller selects Make
|
||
parallelism with the standard `make -jN` option. `JOBS ?= 1` controls only the
|
||
`wwfixture -j N` value passed by `test-compiler`. A normal fast gate can use
|
||
both layers deliberately:
|
||
|
||
```sh
|
||
make -j4 JOBS=4 test-commit
|
||
```
|
||
|
||
For deterministic failure reproduction, make both layers serial explicitly:
|
||
|
||
```sh
|
||
make -j1 JOBS=1 test-commit
|
||
```
|
||
|
||
Serial execution is a debugging mode, not a correctness requirement. `JOBS`
|
||
is not inferred from `MAKEFLAGS`, and there is no jobserver adapter or second
|
||
scheduler hidden in Make.
|
||
|
||
`nocc` remains the separate, explicit reproduction route from a checked-in
|
||
stage-0 snapshot. It is not an implicit prerequisite of ordinary tests or of
|
||
`test-bootstrap`, because it has an external stage-0 precondition.
|
||
|
||
## Compiler fixtures
|
||
|
||
Each fixture is one directory with one `case.ww`. Its first line is exactly one
|
||
of:
|
||
|
||
```text
|
||
//ww:error "required diagnostic fragment"
|
||
//ww:error c "C-stage fragment" ww "WW-stage fragment"
|
||
//ww:compile
|
||
//ww:run
|
||
//ww:run-exit N
|
||
```
|
||
|
||
- `error` requires normal nonzero frontend termination and the declared stderr
|
||
fragment. The labeled form routes distinct fragments to the C and WW cells;
|
||
labels are fixed-order and neither fragment is treated as a shared fallback.
|
||
- `compile` requires frontend exit zero and produces no executable.
|
||
- `run` builds and requires normal program exit zero.
|
||
- `run-exit N` builds and requires normal program exit `N`.
|
||
|
||
Every fixture is run against the C and WW frontends. Signals, launch failures,
|
||
timeouts, build failures, and runtime exits are distinct outcomes.
|
||
`test-compiler` passes `-j $(JOBS)` and therefore uses one fixture slot by
|
||
default. The direct `wwfixture` CLI retains its own four-slot default; pass
|
||
`-j N` when its concurrency must be explicit. Its existing
|
||
`os.exec.start`/`poll` loop supervises the independent processes. Each cell has
|
||
its own working directory; filesystem fixtures use that directory or an
|
||
existing `temp.named` path rather than a shared fixed pathname.
|
||
|
||
The old `TESTS` list and all explicit per-wrapper Make rules are gone. A
|
||
surviving C carrier is registered only by its source file and built through one
|
||
generic pattern rule. Four arena/frontend units share a static rule; the codegen
|
||
unit links the existing private `cgen` and text-emitter objects directly.
|
||
|
||
`test/wwfixture/integration.sh` remains the direct black-box owner for behavior
|
||
that exists only at the command/process/protocol boundary: filtering and list
|
||
output, phase and outcome classification, diagnostic routing, malformed-corpus
|
||
and identity-drift rejection, signal/timeout/interruption cleanup, publication
|
||
failure, and strict result-stream decoding. Semantic fixtures cannot prove
|
||
those observations about their coordinator. `test/wwfixture/process/main.ww`
|
||
owns the lower-level `os.exec` primitives, not the CLI policy layered over
|
||
them, so it is complementary rather than a duplicate owner.
|
||
|
||
The six unit sources have zero active `system`, `popen`, `fork`, or `exec`
|
||
calls. Before direct conversion they contained two `popen` call sites and a full
|
||
`test-unit` run launched one `ww -V` plus twelve `w6c` processes. `400_w6c` now
|
||
checks the same twelve assembly fragments in process, grouped under ten unique
|
||
sources. The CLI version assertion lives with C/WW-driver parity in the existing
|
||
`949_driver_flagargs` integration carrier; `000_smoke` retains its arena-growth
|
||
and nonempty-version-constant assertions.
|
||
|
||
## Package and language behavior
|
||
|
||
`ww test` delegates directory package requests to the native package
|
||
coordinator. The coordinator owns request-pattern expansion, package grouping,
|
||
same-package and external-package action selection, one canonical
|
||
directory-owned product, filtering, result aggregation, and its internal
|
||
temporary workspace. Test sources are exclusively
|
||
`*_test.ww` (Go's `_test.go` contract): a line-leading `@test` declaration in
|
||
any other source is rejected loudly — by both driver stages at directory
|
||
enumeration and by the coordinator at source classification. A local spelling
|
||
containing `...` (for example `ww test lib/...`, Go's `./...` form) is
|
||
recognized by both driver stages before path resolution and walks from the
|
||
directory prefix before the first wildcard. Recursive children beginning `.`
|
||
or `_` and exact `testdata` subtrees are pruned; child directory symlinks are
|
||
not followed. A wildcard cannot consume a non-terminal exact `vendor` element,
|
||
while an explicitly vendor-rooted pattern remains legal. Every selected
|
||
test-bearing directory becomes exactly one package run, binary, and result even
|
||
when both internal and external actions exist. Selected source-bearing
|
||
directories without selected test files report exactly
|
||
`? <package> [no test files]\n` after ordinary production validation, with
|
||
no support, generated main, link, binary, captured runtime result, or process.
|
||
The coordinator first
|
||
launches one driver plan for the complete command-global package/action union.
|
||
After that shared build completes, `-j N` schedules up to N successful selected
|
||
test binaries concurrently under `os.exec` start/poll supervision (no threads);
|
||
emission stays strictly in group order, so the byte stream is identical at
|
||
every `-j` level, and `-j 1` — the default — matches the former sequential
|
||
run loop exactly. Measured on the 31-package `lib/...` walk:
|
||
7.0s sequential, 2.4s at `-j 4`.
|
||
|
||
The raw single-source compatibility route applies package-source eligibility
|
||
before it invokes the compiler or harness. An existing operand ending `.ww`
|
||
whose final requested basename begins `.` or `_` is ignored exactly as it is by
|
||
directory discovery, even when the name also ends `_test.ww`; the file is not
|
||
opened and cannot contribute a test descriptor, package declaration, import,
|
||
variant, graph action, diagnostic, artifact, retained binary, or persistent
|
||
state. A normal explicit running request exits 1 with exact `FAIL\n` stdout and
|
||
the driver's `directory contains no WW package sources` stderr; `-c` and `-S`
|
||
omit the final marker. Visible wrong-platform raw names remain eligible, and
|
||
only the requested basename matters for symlinks (including non-regular
|
||
targets) and hidden parent directories.
|
||
CLI/target and the existing raw package-option shape retain precedence. Cold
|
||
rejection creates no work or temporary product; warm rejection preserves prior
|
||
work and public bytes without transaction residue. The focused
|
||
`named_source_prefixes_are_ignored` package observer proves these rules in both
|
||
driver stages, including malformed/import precedence, prefix-before-test and
|
||
platform classification, symlink spelling, output rollback, residue, and
|
||
diagnostic/artifact parity. Directory package coordination and test process,
|
||
filter, timeout, signal, and descendant topology are unchanged.
|
||
|
||
The corresponding focused dual-stage named-test-source build observer proves
|
||
the distinct `ww build` rule for one visible raw operand ending exactly
|
||
`_test.ww`. It requires each stage to read the package clause and contiguous
|
||
initial imports before omitting the sole root: unreadable/header-syntax inputs
|
||
retain their diagnostics, while a valid header prevents import resolution,
|
||
graph/action creation, producers, runtime, publication, persistence, and all
|
||
ordinary body-derived diagnostics. It separately proves that a first malformed
|
||
UTF-8 or non-leading BOM body byte is outside the header, while a reached NUL
|
||
and an unterminated header-trivia comment retain loader diagnostics. It also
|
||
proves WW's grammar-level adaptation of Go's following-`i` byte probe: only the
|
||
exact lexical `import` token continues the header, while an identifier such as
|
||
`imported` begins the ordinary body. It covers
|
||
normal, `-S`, and `/dev/null` successful
|
||
empty selections; the exact `no packages to build` and `no main packages to
|
||
build` output branches; requested-basename prefix, symlink, symlink-directory,
|
||
and wrong-platform spelling controls; cold absence and warm preservation of
|
||
outputs/work state; tool/process absence, interruption, concurrency, and
|
||
residue cleanup. Cstage and WWstage agree on status, stdout, stderr,
|
||
diagnostics, semantic artifact/work snapshots, and unaffected-control artifact
|
||
bytes. Complete per-stage warm snapshots additionally cover the intentionally
|
||
stage-specific `.wwtool.ww` producer-provenance file.
|
||
Raw `ww test`, `-c`, and `-S` test routes retain explicit test-file selection;
|
||
directory/recursive selection, package/import identities, graph/action
|
||
identities, persistence formats (build 18, test 19, semantic 3), and test
|
||
process topology are explicit non-effects.
|
||
|
||
Exact `package documentation` is a separate source-suppression rule after the
|
||
completed filename, target, file-kind, and test-role gates. Official Go 1.26.5
|
||
`go/build` directly implements the exclusion after package/import-header
|
||
loading and before `_test.go` or package-family classification. Its
|
||
`read_test.go` directly tests the ordinary-body stop and malformed-import
|
||
recovery, but the pinned official test/testdata tree has no test that directly
|
||
names `package documentation`; `mod_doc.txt` is unrelated. That test absence is
|
||
recorded rather than replaced with host-Go behavior.
|
||
|
||
The focused package observer is therefore WW-native dual-stage proof. It
|
||
covers one leading BOM, whitespace/comments/internal line directives and
|
||
package-clause trivia; exact-name controls; malformed package and contiguous
|
||
import headers; the raw body-boundary `i` that does not form exact `import` and
|
||
must diagnose `expected top-level decl`; and ignored non-`i` bodies containing
|
||
late imports, missing imports, declarations, initializers, `@test`, aborts, or
|
||
nonzero mains. It also covers literal and logical single files, direct and
|
||
recursive directories, the unchanged one-file import-decoy boundary, dotted
|
||
directory providers, mixed and doc-only source sets, and exact Cstage/WWstage
|
||
status, stream, source-set, diagnostic, and semantic-artifact parity.
|
||
|
||
Named-file documentation preflight is restricted to sources whose
|
||
symlink-following `stat` result is regular, including symlinks to regular
|
||
files. It retains one exact read buffer: documentation sources are suppressed
|
||
from it, while ordinary sources carry those same bytes into graph loading.
|
||
FIFO and other nonregular named-source routes are untouched. Coordinator
|
||
directory discovery is metadata-only; after canonicalization and deduplication,
|
||
each unique selected source is classified exactly once. Buffered ordinary
|
||
bytes are then reused for coordinator source validation, and per-request
|
||
direct/recursive error, match, and group accounting follows classification.
|
||
The delegated driver separately owns a request-graph directory observation:
|
||
one canonical membership list and one lazy regular-source snapshot feed every
|
||
reached production/test variant, including package-name/`@test` checks, import
|
||
scanning, copied test actions, and unit emission. Production-only selection
|
||
still does not open excluded `*_test.ww` files. The coordinator and delegated
|
||
driver retain their separate process observations; the slice does not promise
|
||
an atomic source snapshot across a concurrent rewrite between them.
|
||
|
||
The test route matrix remains intentional. A visible literal named
|
||
`_test.ww` build validates only its package/import header and then follows the
|
||
existing test-only empty-selection rule; it does not run documentation
|
||
classification or the synthetic raw-`i` check. Directory production leaves
|
||
`*_test.ww` unopened. Raw `ww test` and selected directory test variants do
|
||
classify exact documentation sources, while a logical request whose resolved
|
||
provider merely has an `_test.ww` physical basename is not the literal named
|
||
build special case. Directory `test -S` without its required `-o` first rejects
|
||
with `ww test: -S needs -o`; after a valid `-o`, a directory rejects with
|
||
`ww test: -S needs a single test file`. Both branches precede documentation
|
||
classification.
|
||
|
||
A doc-only direct running directory test exits 1 with exact `FAIL\n` stdout and
|
||
the coordinator's no-source stderr; `-c` has the same error and empty stdout.
|
||
A doc-only named or logical raw running test likewise emits `FAIL\n` plus the
|
||
driver's physical-parent no-source diagnostic; raw `-c` and `-S` have empty
|
||
stdout. A documentation-header error precedes no-source, with `FAIL` added only
|
||
by an explicit running raw or directory/recursive test. Recursive doc-only
|
||
patterns become no matches: running test emits the per-pattern warning then
|
||
`ww test: no packages to test`, while mixed patterns retain and run only
|
||
ordinary groups without warning. A directly named doc-only sibling root fails
|
||
discovery for the complete request before any group starts.
|
||
|
||
Suppression happens before package folders, internal/external families,
|
||
products, graph edges, support, generated main, or execution. The documentation
|
||
source creates no compiler, assembler, archiver, linker, test child, capture,
|
||
result, retained binary, public output, work-state artifact, transaction, or
|
||
persistence key. Mixed products and semantic artifacts equal the source-absent
|
||
control byte for byte; changing only an ignored documentation body cannot
|
||
invalidate or replace a committed generation. Cold failure publishes nothing,
|
||
warm header/no-source failure preserves prior public and semantic bytes, and
|
||
normal request-private cleanup and concurrency isolation remain unchanged.
|
||
The known external-driver fixed-`.new` interruption poisoning remains open.
|
||
Build workdir format remains 18, test workdir format remains 19, and semantic
|
||
storage format remains 3; no test-result cache, schema, action descriptor,
|
||
transaction marker, or lock is introduced.
|
||
|
||
The blank declared package name has a different contract from documentation
|
||
suppression. The sole authority is official Go 1.26.5 at commit
|
||
`c19862e5f8415b4f24b189d065ed739517c548ba`:
|
||
|
||
- **behavior directly implemented or asserted by pinned Go** — the compiler
|
||
scanner admits and dispatches `_` through its name path
|
||
(`cmd/compile/internal/syntax/scanner.go:88–107,368–394,437–439`), the parser
|
||
accepts it in package syntax (`parser.go:397–420,2751–2763`), and types2
|
||
rejects the retained node as `invalid package name _`
|
||
(`cmd/compile/internal/types2/check.go:336–355`).
|
||
- **behavior directly implemented or asserted by pinned Go** — official
|
||
`test/blank1.go:1–31` asserts the blank-name error and later checker errors,
|
||
proving continuation. `internal/types/testdata/check/blank.go:1–5` asserts
|
||
only the blank-name error. `cmd/go/testdata/script/build_test_only.txt:1–18`
|
||
and `build_no_go.txt:1–30` are surrounding source-role controls.
|
||
- The official tree contains no cmd/go blank-name matrix for named, multiple,
|
||
mixed, imported, test-only, action, artifact, rollback, concurrency, or
|
||
interruption cases; the focused WW package observer owns those proofs.
|
||
- **behavior directly implemented or asserted by pinned Go** — types2
|
||
validates an importer-supplied package object before applying its local
|
||
alias. Provider name `_` emits
|
||
`could not import PATH (invalid package name: "_")` at the source import
|
||
path, caches a path-leaf-named fake package, marks the use, and continues
|
||
(`cmd/compile/internal/types2/resolver.go:125–180,248–335`; public twin
|
||
`go/types/resolver.go:157–190,263–350`). An empty provider name quotes the
|
||
actual empty value instead.
|
||
- No official pinned test directly supplies an imported `Package` named `_`.
|
||
**behavior derived from the pinned implementation** — the
|
||
imported-interface rows are WW-native proof of applying those resolver
|
||
semantics to WW's supported source-like interface channel.
|
||
|
||
The slice is not owned only by the four primary parser/checker files. The two
|
||
`w6c` command fronts own test-support materialization, imported-package
|
||
metadata, reachability/filtering, fake qualifier assignment, and delayed AST
|
||
concatenation; the checker twins own deduplicated diagnostics and empty-scope
|
||
fake recovery; the AST/parser twins own the independent path-token position.
|
||
The package coordinator and public drivers exercise the same interface channel
|
||
without redefining package or action identity.
|
||
|
||
The coordinator treats `_` as a syntactically loaded declared name, not a
|
||
generic missing-clause error. A production-only blank package under `ww test`
|
||
selects its one ordinary production compiler action and fails there. Blank
|
||
production plus a same-package blank `_test.ww` selects one augmented internal
|
||
test action containing both source sets. `sep_recompile_for_test` substitutes
|
||
that action for the separate production node throughout the product closure,
|
||
so it is compiled once and emits one `invalid package name _` per retained
|
||
source marker in deterministic unit order. A test-only blank `_test.ww` forms
|
||
one test-only internal action and reports once. Valid production `p` plus blank
|
||
test `_`, or blank production `_` plus an unrelated `p` or `p_test`, keeps the
|
||
existing family-mismatch rejection before tools. Blank production plus the
|
||
actually related external name `__test` passes family classification, but the
|
||
production dependency fails before the external action, support/generated
|
||
main, link, or runtime completes.
|
||
|
||
The observable test phase order is selected-source validation and package/test
|
||
family classification, recursive import loading, eligible dependency and
|
||
support producers, complete parent-source parsing, blank-name checking,
|
||
imported-package validation, later checker diagnostics, and the
|
||
existing package failure trailer. A missing or invalid dependency may
|
||
therefore suppress both a later body syntax diagnostic and BlankPkgName; a
|
||
complete-file syntax error suppresses checker diagnostics.
|
||
Raw and directory running requests keep their established command-owned
|
||
`FAIL\n` placement, while `-c` and applicable `-S` paths retain empty stdout.
|
||
Directory `-S` option-shape errors remain earlier than source selection. No
|
||
blank product begins a test or user runtime.
|
||
|
||
The imported-interface observer uses the supported repeatable
|
||
`w6c -c --import PATH FILE.wwi` channel and its public persistent build/test
|
||
equivalent. Each compiler first read/owner/syntax-checks sorted standalone
|
||
interfaces, then parses primary source. Primary syntax failure precedes
|
||
imported-package semantic validation. After successful primary syntax, `-T`
|
||
materializes a missing compiler-required `test` or collision-safe `__wwtest`
|
||
use in the primary list before resolution. It is marked used and rooted at the
|
||
generated primary file position. With no matching import it keeps the existing
|
||
external-support fallback; with a matching blank-named interface it receives
|
||
the ordinary invalid-provider diagnostic. Existing explicit test-target roots
|
||
already have a primary occurrence and are not duplicated.
|
||
|
||
The observer requires metadata classification as valid, missing, conflicting,
|
||
or invalid, followed by reachability seeded solely by canonical primary and
|
||
compiler-required uses. Only a reached valid interface owner may contribute
|
||
transitive imports. Before binding and delayed concatenation, invalid-owner,
|
||
unreachable, and ownerless standalone facts are removed. The unused-interface
|
||
control includes a mixed-origin invalid interface whose embedded valid origin
|
||
imports the bad path: because that origin is not independently rooted, the
|
||
whole interface is inert and the primary outputs equal the no-interface
|
||
control. A companion primary-reached origin proves that legitimate traversal
|
||
does reach and diagnose the bad provider.
|
||
|
||
For every retained bad use, default, explicit, and blank aliases all validate
|
||
the provider name. Nonblank uses receive an explicit-alias or canonical-path-
|
||
leaf fake binding with empty scope; blank uses install none. All are marked
|
||
used. Qualified value/call/type recovery produces no missing-member,
|
||
unknown-type, export, or calling-nonfunction cascade, while lexical shadowing
|
||
still applies. One canonical bad path emits one diagnostic despite repeated
|
||
occurrences; two paths emit one each in retained order, and an independent
|
||
checker diagnostic follows. Every source-created form points at the path's
|
||
first identifier, not the explicit alias. The compiler-generated support use
|
||
uses its generated root position because no path token exists.
|
||
|
||
Public proof corrupts a caller-owned committed provider `.wwi`, then exercises
|
||
build and test consumers through the existing canonical interface action.
|
||
Reached corruption fails the affected compiler action before its assembler and
|
||
downstream archive, link, retention, or runtime. A package-action failure
|
||
prevents generated main; a generated-main action that is itself the consumer
|
||
performs the same validation before its assembly. A same-named `.ww` file is
|
||
still an import decoy. Raw, production, internal, external, test-only,
|
||
generated-main, `-c`, and applicable `-S` shapes share the same validation.
|
||
Prior public, retained, and semantic bytes survive, invalid bytes cannot commit
|
||
a replacement consumer, and restoring valid interface bytes follows ordinary
|
||
reuse. An unreferenced corrupt interface remains inert and causes no
|
||
invalidation.
|
||
|
||
The package-name token does not alter production/internal/external/recompiled,
|
||
support, or generated-main identities. Direct actions retain `__root`, dotted
|
||
actions retain dotted identity, and no successful ordinary producer interface
|
||
can advertise a blank provider. A supplied or corrupted interface that does is
|
||
invalid consumer input. A failed primary blank action or reached invalid
|
||
interface consumer emits no assembly or interface, so its assembler, archiver,
|
||
linker, generated main, harness, and runtime do not run; earlier valid
|
||
dependency/support producers may run normally. Request rollback removes owned
|
||
stages and commits no failed unit, interface, assembly, object, archive, binary,
|
||
status, retained output, or tool stamp. Warm prior public and semantic bytes
|
||
remain unchanged, exact source/interface restoration uses ordinary reuse, and
|
||
concurrent requests keep parser/checker reachability, deduplication, fake
|
||
bindings, and cleanup independent.
|
||
|
||
Direct `w6c`/`w6c_ww` and public `ww`/`ww_ww` are required to agree on status,
|
||
stdout, exact path-token positions and diagnostic order, fake recovery, output
|
||
absence, and prior-byte preservation for the full role/import matrix. The
|
||
syntax/check change adds no test-process topology, test-result cache, schema,
|
||
action descriptor, or stored identity. Private in-memory `N_USE` nodes gain
|
||
only path-position fields; AST enum/printing and `.wwi` serialization are
|
||
unchanged. Build workdir format remains 18, test workdir format remains 19, and
|
||
semantic storage format remains 3. Normal checker failure leaves no anonymous
|
||
descriptor, adjacent stage, request residue, or child. External-driver SIGTERM
|
||
supervision is unchanged: the known orphan compiler, fixed `.new` staging, and
|
||
later persistent-request poisoning remain open and are not credited to this
|
||
slice.
|
||
|
||
The run front has one separate post-target argument contract. The sole
|
||
authority is official Go 1.26.5 at commit
|
||
`c19862e5f8415b4f24b189d065ed739517c548ba`:
|
||
|
||
- **behavior directly implemented or asserted by pinned Go** — command flag
|
||
parsing supplies only its positional suffix to `runRun`
|
||
(`cmd/go/main.go:312–322`; `flag/flag.go:1074–1089,1149–1176`), and
|
||
`runRun` consumes the named-file prefix or one package before attaching the
|
||
untouched suffix to the run action
|
||
(`cmd/go/internal/run/run.go:96–140,170–173`).
|
||
- **behavior directly implemented or asserted by pinned Go** — official
|
||
`cmd/go/testdata/script/mod_run_flags_issue64738.txt:1–4` proves that
|
||
target-following `-p ignored` is program input rather than a Go-command
|
||
option. `cmd/go/testdata/script/run_dirs.txt:1–20` anchors the independent
|
||
contiguous named-file prefix, which WW does not claim here.
|
||
- **behavior derived from the pinned implementation** — after WW's one
|
||
explicit local run target, every remaining operand is runtime argv. The
|
||
rule honestly applies without importing Go modules or manifests. WW's
|
||
default-dot extension has no explicit target boundary, and leading or
|
||
pre-target `--` remains its existing unknown flag rather than gaining
|
||
general Go flag-terminator semantics.
|
||
|
||
Before the repair, **directly measured WW behavior** was stage-equal but
|
||
different: both drivers rejected immediately target-following `-p ignored` and
|
||
`-- -p ignored` at status 2 with empty stdout and exact unknown-flag stderr,
|
||
consumed target-following `-o` and `-I` values as driver configuration, and
|
||
passed the ordered suffix only after a second nonflag. Accepted controls loaded
|
||
one target and its ordinary import closure and completed the private compiler,
|
||
assembler, archiver, linker, and runtime route; rejected rows stopped before
|
||
loading, actions, tools, runtime, or scratch.
|
||
|
||
The focused `run_post_target_arguments_are_program_argv` observer owns the
|
||
completed boundary in `test/package/package_test.ww`. Across Cstage and WWstage
|
||
it uses both a literal named source and a directory package and requires exact
|
||
ordered delivery for separate and joined known-option spellings, unknown
|
||
options, would-be values, a singleton value-taking spelling, `--`, later
|
||
nonflags and `.ww`, and an empty string. It separately requires pre-target
|
||
options and their missing/unknown diagnostics to remain driver-owned, leading
|
||
`--` to keep its current rejection, no-operand run to keep default-dot
|
||
selection, and target load/producer diagnostics to precede inert suffix bytes.
|
||
Valid programs expose the private executable at `os.args()[0]`, receive the
|
||
exact suffix at indices 1 onward, and retain WW's existing stdout, stderr, and
|
||
exact child-status mapping. Pinned Go's distinct command-level nonzero status
|
||
mapping (`cmd/go/internal/run/run.go:56,198–210` and
|
||
`cmd/go/internal/base/base.go:218–246`) remains an open difference.
|
||
|
||
The observer also treats all four permanent axes as one contract. The build/run
|
||
axis changes only the parser-to-child boundary. Build and test controls retain
|
||
their status, streams, action inputs, and comparable artifact bytes. Package
|
||
membership and command classification still come only from the selected
|
||
target, while dotted-import resolution, edges, interfaces, visibility, and
|
||
initialization still come only from that target's closure. Direct actions
|
||
remain `__root.*`; dotted directories retain dotted identity; argv creates no
|
||
package, import, graph, action, symbol, artifact, `.wwi`, publication,
|
||
persistence, reuse, or invalidation identity.
|
||
|
||
Post-target bytes therefore cannot change compiler, assembler, archiver,
|
||
linker, initializer, or private executable bytes. Run publishes no public
|
||
product or semantic state. Normal success, target/producer failure, runtime
|
||
nonzero, and overlapping requests must keep suffixes isolated and remove each
|
||
owned private executable, `.sepwork`, stage, transaction, capture, result,
|
||
request, descriptor, and child. Cstage and WWstage must agree on stable status,
|
||
stdout, stderr, diagnostic order, runtime argv, cleanup, and comparable
|
||
artifact bytes. No AST, interface, descriptor, request, transaction, or
|
||
persistent schema changes; build workdir format remains 18, test workdir format
|
||
remains 19, semantic storage format remains 3, and no test-result cache is
|
||
introduced.
|
||
|
||
The observer makes no claim for regular or missing `_test.ww`, missing `.ww`,
|
||
hidden named sources, multiple leading source operands and source-set
|
||
boundaries, literal nonregular named sources, shared test-package state,
|
||
panic/exit/Fatal/FailNow topology, Go-compatible RE2 `-run`, three-way
|
||
no-buildable-source causes, or Go-like run exit-status mapping. External-driver
|
||
SIGTERM supervision is also unchanged: the verified orphan compiler, three
|
||
fixed `.new` stages, and later persistent-request poisoning remain open.
|
||
|
||
An existing local directory whose requested build basename ends `.ww`
|
||
(including a visible `_test.ww` symlink to a directory) remains a directory
|
||
package, not a raw named test source. WWstage `ww build` now uses the same
|
||
symlink-following requested-kind decision as Cstage and enters the established
|
||
directory coordinator. The directory's actual `*_test.ww` entries remain
|
||
excluded from production and available to `ww test`; the requested suffix does
|
||
not itself create a test variant. Raw `ww test`, `test -c`, and `test -S` were
|
||
already stat-routed and do not change. The focused package observer directly
|
||
measures Cstage/WWstage build diagnostics and semantic/public artifact-byte
|
||
parity, direct and symlinked `.ww` directories, a dotted dependency, output
|
||
modes, cold/warm transaction behavior, compiler and signaled-linker failure
|
||
preservation, selected-route concurrency, cleanup, and the exact test-command
|
||
behavior. Direct driver interruption remains owned by the unchanged directory
|
||
machinery and is not claimed fixed here.
|
||
|
||
Pinned Go's run command has a distinct suffix-first named-file front door.
|
||
Accordingly, an existing `ww run` target whose exact requested spelling ends
|
||
`.ww` and whose symlink-following `stat` result is a directory is rejected in
|
||
the twin run fronts before the shared resolver and private run scratch. An
|
||
`_test.ww` spelling emits exactly
|
||
`ww: cannot run *_test.ww files (OPERAND)\n`; every other selected `.ww`
|
||
directory emits exactly `OPERAND is a directory, should be a WW file\n`.
|
||
Both stages return status 1 with empty stdout, open no directory member, scan
|
||
no import, construct no package/graph/action, invoke no producer or runtime,
|
||
and create no run scratch or artifact. This includes direct and symlinked
|
||
directories and hidden directory spellings; directory contents cannot displace
|
||
the classifier diagnostic. A trailing separator and non-`.ww` or dotted
|
||
package requests retain the directory package route. The same-spelling build,
|
||
raw test, `test -c`, and directory `test -S` routes remain stat-first and keep
|
||
their existing diagnostics and artifact bytes. Thus this run change creates no
|
||
test product, result, package/import identity, test-process/filter change, or
|
||
serialized-format change; build remains 18, test remains 19, and semantic
|
||
storage remains 3. Regular or missing `_test.ww`, missing/logical `.ww`,
|
||
multiple named sources, finite FIFOs, and hidden regular sources are not
|
||
claimed by this existing-directory slice. The general direct-driver `.new`
|
||
interruption residue also remains open.
|
||
|
||
The raw source front also applies one positive requested-spelling gate before
|
||
physical adoption. An existing non-directory operand whose exact requested
|
||
spelling does not end `.ww` is not a raw source and cannot hijack its ordinary
|
||
dotted provider. Build, run, raw test, the historical second-positional raw
|
||
test filter, `test -c`, and `test -S` therefore resolve and consume the same
|
||
logical file or directory they consume when the collision is absent. Logical
|
||
files keep the existing `__root` action/artifact family; logical directories
|
||
keep dotted package/import/action identity. The ignored object's bytes,
|
||
package, imports, tests, runtime status, mode, and timestamp supply no package
|
||
membership, edge, producer input, artifact, publication, or persistence key.
|
||
|
||
Requested suffix owns the gate through symlinks. Wrong-suffix links to regular
|
||
or special non-directories remain logical requests, while a link to a directory
|
||
retains stat-first direct-directory routing; a visible `.ww` link to a regular
|
||
source remains raw source. Each stage's existing visible `.ww` special-file
|
||
handling is outside this slice. Mutation/reuse invariance is limited to absent
|
||
or stat-successful non-directory collision states. A transition to a directory
|
||
uses the directory owner and receives no new concurrent-kind snapshot promise.
|
||
|
||
No-provider rows deliberately separate the ordinary single-target path from
|
||
the second-positional compatibility path. The first retains direct cannot-find
|
||
diagnostics, running-test `FAIL`, and producer/artifact absence. The second
|
||
retains the existing package-coordinator process, canonicalization or usage
|
||
diagnostic, status, selection state, and cleanup; the gate does not turn that
|
||
route into a direct raw-file error. Logical producer failure preserves prior
|
||
public and semantic bytes. A retained running-test runtime failure instead
|
||
keeps the complete newly built semantic generation committed and reusable but
|
||
skips deferred installation, preserving prior retained public bytes; restoring
|
||
the old source requires a later successful rebuild and commit. Normal and
|
||
controlled-failure cleanup is unchanged. External driver signals after action
|
||
start retain the open fixed
|
||
`.new` leakage and later-request poisoning behavior.
|
||
|
||
The focused `wrong_suffix_physical_files_do_not_hijack_dotted_requests`
|
||
package observer owns this boundary for both driver stages. It compares absent
|
||
controls with regular, symlinked-regular, and symlinked-special collisions;
|
||
checks build, run, raw/filter test, `-c`, and `-S` streams, statuses, runtime,
|
||
public bytes, complete comparable semantic artifacts, `__root` file identity,
|
||
and dotted directory identity; separates direct and coordinator no-provider
|
||
rows; exercises warm non-directory mutation, producer-failure rollback,
|
||
retained-runtime-failure public-byte preservation with committed semantic-
|
||
generation reuse and later successful restoration, request-local concurrent
|
||
builds, positive `.ww` and direct-directory controls, and normal residue
|
||
cleanup. It makes no finite-FIFO or signal-recovery claim.
|
||
The rule changes no package coordinator, test harness/process topology,
|
||
test-result caching, or build/test/semantic format (18/19/3).
|
||
|
||
List mode uses that same product process and initialization boundary but starts
|
||
no per-test child. The shared language harness emits only selected qualified
|
||
test names, one per line in descriptor order. A valid filter selecting no tests
|
||
therefore produces no harness list bytes, warning, or accounting while the
|
||
process returns success; the coordinator continues with the package's normal
|
||
unsuffixed `ok` result. Ordinary non-list zero-selection execution instead
|
||
writes the exact line `testing: warning: no tests to run` through harness
|
||
stderr, retains its accounting and successful status, and gives the successful
|
||
package `ok` result the suffix ` [no tests to run]`. Marker recognition is
|
||
line-delimited, at capture byte zero or after a newline; an arbitrary substring
|
||
in user output does not annotate the result. Concurrent products keep
|
||
independent empty or nonempty captures, markers, and suffixes, and persistent
|
||
work never caches a test result. A directly invoked retained binary exposes the
|
||
warning on stderr and accounting on stdout because no coordinator combines its
|
||
descriptors or emits a package result.
|
||
|
||
The shared language runtime accepts `test.skip("")` as a successful skip. Its
|
||
zero-length reason is a structurally valid skipped control result, so a normal
|
||
zero child exit produces the existing `qualified.name ... SKIP: ` line followed
|
||
immediately by newline, increments skipped accounting, and contributes neither
|
||
a failure nor a harness error. Later selected tests continue. This one runtime
|
||
classification covers raw single-file, same-package, external-test, and honest
|
||
test-only descriptors, an active-test call reached through production package
|
||
code, filtered execution, coordinator-run retained binaries, and later direct
|
||
retained-binary execution. Production files still define no test-body
|
||
descriptor. Nonempty skips are unchanged; an oversized reason is still an
|
||
invalid harness result, and skip outside an active test still aborts. List mode
|
||
still executes no body. This rule does not merge per-test children or change
|
||
package/import initialization, product scheduling, timeout and process-group
|
||
ownership, publication, persistence, or cleanup.
|
||
|
||
Directory test binaries are always linked under the coordinator's temporary
|
||
product root. The retained-output option has the exact registered name `o` and
|
||
accepts `-o VALUE`, `--o VALUE`, `-o=VALUE`, and `--o=VALUE`. An equals form
|
||
splits only at its first `=`, preserving an empty value and any later `=`
|
||
bytes. Repeated occurrences are last-value-wins. A final empty value is no
|
||
effective explicit output: it requests no retained copy for a running test,
|
||
while `-c` falls back to the ordinary `<import-leaf>.test` name. Concatenated
|
||
`-oVALUE` and `--oVALUE` spell unknown flags and reject before loading, product
|
||
construction, tools, execution, or publication. Known test flags, including
|
||
these exact output forms, remain recognized before or after package operands.
|
||
`-c` independently requests a caller-visible executable copy and suppresses
|
||
execution. A nonempty effective `-o` independently requests a copy and still
|
||
runs the temporary binary unless `-c` is also present. Without an effective
|
||
explicit output, `-c` publishes `<import-leaf>.test` in the invocation
|
||
directory; an output ending in `/` or naming an existing directory receives
|
||
one such name per selected package and missing parents are created. A single
|
||
non-directory output is legal for one package only. Multi-package
|
||
non-directory output and duplicate visible binary
|
||
names reject before tools; exact `/dev/null` discards every copy and permits
|
||
duplicate names. The private test link still runs unless `-c` suppresses it;
|
||
the raw single-file compatibility route also links into driver-owned private
|
||
storage instead of using `/dev/null` as an artifact or `.sepwork` stem. A
|
||
package with no selected test source validates production, reports the same
|
||
`[no test files]` result, publishes nothing, and does not create an otherwise
|
||
unneeded output directory. Successful `-c` output is silent apart from that
|
||
no-test-files report.
|
||
|
||
The package suite also pins the adjacent `ww build` output-directory branch.
|
||
After normal loading, an existing directory (including a symlink to one) or an
|
||
explicit spelling ending in `/` receives each command under its requested
|
||
import-leaf name (or local directory-leaf fallback) even for exactly one
|
||
selected root; a raw `.ww` command uses its source basename. A missing
|
||
trailing-slash hierarchy is created from `0777`, filtered by umask, by the
|
||
request transaction. A directory or raw no-main-only selection and an import
|
||
failure run no tools and do not create output. Independently selected non-main
|
||
siblings in a mixed request load but have no action; command dependencies still
|
||
build. Package/import rejection precedes no-main, derived destination length,
|
||
duplicate command basename, and implicit default-directory preflight. If the
|
||
synthesized default command basename already exists as a directory,
|
||
load/graph validation precedes a zero-tool rejection and preserves that
|
||
directory; a non-main package has no corresponding default output.
|
||
Persistent work reuse, invalidation, failures, interruption, and
|
||
concurrent drivers retain the same action and rollback rules; output form does
|
||
not enter package/import/action identity. This build branch starts no runtime
|
||
process, while direct execution of its published binary remains an artifact
|
||
check rather than part of `ww build`. Assembly-only `-S` still selects command
|
||
actions and rejects a no-command directory request, but it performs no
|
||
install-only destination validation or output-directory creation.
|
||
|
||
Package declaration checking also precedes test execution. In a package whose
|
||
declared name is `main`, `let main`, `const main`, `def main`, and `type main`
|
||
are rejected by both compiler stages as `cannot declare main - must be func`
|
||
and are not installed into package scope. The generated directory-test main is
|
||
an independent tool-owned action and cannot mask the malformed production or
|
||
same-package declaration: the product emits no test body output, accounting,
|
||
or `ok` result. This condition keys only on the source-declared package name;
|
||
a package with another declared name may export `main` even when its dotted
|
||
path or physical leaf is `main`, and WW's supported argument/result-bearing
|
||
function entries remain valid. The native
|
||
`nonfunction_main_declarations_reject` observer covers all four declaration
|
||
kinds, direct compiler ownership, build/test diagnostics, command-import
|
||
precedence, declared-name/import identity, valid artifact bytes, cold cleanup,
|
||
and warm work/output rollback and reuse across both stages.
|
||
|
||
The retained executable is byte-identical to the temporary runnable and has
|
||
executable mode `0777` filtered by the caller's umask, but it is never the path
|
||
executed by the coordinator. Compile-only publication participates in the
|
||
driver's one request-wide transaction: producer, linker, staging, or
|
||
installation failure preserves every prior destination and removes stages and
|
||
newly created output prefixes. A running retained request instead withholds
|
||
the public path from that build transaction. The coordinator runs the private
|
||
binary, then invokes the selected stage driver's guarded install action only
|
||
after a successful process result. Failure, signal, timeout, interruption, or
|
||
child-start failure therefore preserves any prior retained binary and creates
|
||
no new one. Successful products install independently after their runs. The
|
||
language runtime owns individual `@test` functions.
|
||
|
||
Every build or retained-test public install follows Go 1.26.5's late
|
||
destination safety rule. After applicable producers (and, for running tests,
|
||
after the successful run), ordinary `stat` rejects a directory and rejects a
|
||
nonempty regular non-object file. Empty reservations, recognized prior
|
||
outputs, and non-directory non-regular paths remain replaceable. Recognition
|
||
uses Go's archive/ELF/Mach-O/PE/Plan 9/WASM/XCOFF magic plus WW's narrow
|
||
`//ww:module ` interface prefix. Package/import rejection keeps its earlier
|
||
diagnostic precedence; exact `/dev/null` and `-S` never enter the guard.
|
||
|
||
Every actually executed directory product gives its single generated binary
|
||
the product's canonical absolute physical source directory as child cwd. A
|
||
fresh per-run environment removes inherited exact uppercase `PWD` entries and
|
||
appends one `PWD` with that same directory, matching Go 1.26.5's observable
|
||
`AppendPWD` plus last-value-wins `os/exec` behavior. The coordinator's cwd and
|
||
environment do not change, and overlapping `-j N` children share no writable
|
||
environment vector. Relative ordinary data, `testdata`, and writes resolve in
|
||
the tested directory. Production and test-only dependency initializers run in
|
||
that product process and see its directory; separately testing the dependency
|
||
creates a separate process using the dependency directory. Equivalent direct,
|
||
recursive, redundant, absolute, and root-symlink spellings converge before
|
||
this runtime field is assigned.
|
||
|
||
Every test binary actually executed by either driver stage also receives one
|
||
effective uppercase `PATH` beginning with the canonical absolute directory of
|
||
the selected WW driver. Missing and empty caller values produce only that
|
||
directory; a nonempty first effective caller value follows it after `:`.
|
||
Normal duplicate `PATH=` entries collapse to the one child value. Directory
|
||
products allocate this environment independently per concurrent child; the raw
|
||
single-file route performs the same PATH transformation while retaining its
|
||
caller cwd, `PWD`, stdin, and split streams. Running retained tests transform
|
||
the private run and install only after success. Compile-only, assembly-only,
|
||
no-test, rejected, and build requests start no test process and therefore have
|
||
no test-PATH state.
|
||
|
||
For a directory product, the rest of the child vector is a Go-like snapshot of
|
||
the caller environment rather than the build-tool environment: the first
|
||
case-sensitive occurrence of every normal `key=value` survives, later normal
|
||
duplicates and raw empty entries do not, and nonempty malformed entries remain
|
||
in order. Only the effective `PATH` and package `PWD` are then appended.
|
||
Caller `LC_ALL`, `TMPDIR`, empty values, case-distinct keys, and arbitrary
|
||
variables therefore reach dependency initialization and selected tests.
|
||
Build-plan compiler, assembler, archiver, linker, and scratch environments keep
|
||
their existing pinned locale and request-private temporary directory.
|
||
|
||
Every such product also receives an independently opened null device as fd 0.
|
||
Caller terminal, pipe, and file bytes remain with the coordinator; serial and
|
||
parallel products observe immediate EOF rather than consuming a shared input
|
||
offset. Production and test-only dependency initialization, filters, list mode,
|
||
no-match execution, failure, and timeout use that same process boundary.
|
||
|
||
The same product maps fd 1 and fd 2 to one open product-local capture. This
|
||
matches Go's test-command use of one writer for `exec.Cmd.Stdout` and
|
||
`exec.Cmd.Stderr`: writes are not drained into two files and regrouped later.
|
||
The coordinator emits the completed combined bytes and any product run-status
|
||
line on stdout. Before its existing directory-product `ok` or run-status
|
||
`FAIL` trailer, it emits exactly one newline when that capture is nonempty and
|
||
does not already end in newline. Empty and newline-terminated captures gain no
|
||
byte. Raw single-file and later direct retained-binary execution have no
|
||
coordinator trailer, so their bytes remain untouched. Each parallel product
|
||
has a distinct capture, while canonical group-order emission remains
|
||
byte-stable across `-j` values. Build-plan stdout and stderr stay distinct, and
|
||
loader/build diagnostics stay on stderr.
|
||
|
||
After canonical result emission, an ordinary test command with any explicit
|
||
directory, recursive, dotted-directory, or raw-file target emits exactly one
|
||
final standalone `FAIL\n` when attributable setup, build, or test execution
|
||
failed. It follows later successful package output and applies to filters, list
|
||
mode, signals, timeouts, executable-start failures, and running retained tests.
|
||
The bare implicit-current-directory form, `-c`, `-S`, build requests, CLI
|
||
usage/shape or output preflight, publication-only, capture-only, cleanup-only,
|
||
and direct retained-binary execution do not receive the command marker.
|
||
Directory coordination and both raw-file drivers own only this final
|
||
presentation state; test captures, result trailers, diagnostics, scheduling,
|
||
rollback, artifact bytes, and persisted action identity remain unchanged.
|
||
|
||
The physical directory remains distinct from exact dotted package identity and
|
||
from production, internal, external, recompiled, support, and generated-main
|
||
action identity. Only product execution uses it. Compiler, assembler, archiver,
|
||
linker, support, and generated-main commands retain their build-plan cwd and
|
||
environment. Captured directory build plans begin with null stdin, which their
|
||
inherited-stdio tool descendants retain. `ww build`, `ww test -c`, `-c -o`, and
|
||
no-selected-test products start no test child. A published test binary run
|
||
directly inherits the user's cwd/environment/stdin. The raw single-file
|
||
compatibility path inherits caller cwd/stdin and all unrelated environment
|
||
entries, with only the test-PATH transformation above; neither route embeds a
|
||
package directory or input behavior in the binary.
|
||
|
||
Before package grouping, both directory drivers and the shared recursive
|
||
coordinator apply Go 1.26.5's filename OS/architecture rule for WW's fixed
|
||
`linux/amd64` target. The basename stem ends at its first dot; a final `_test`
|
||
token is removed for matching; a recognized OS/architecture pair takes
|
||
precedence over a recognized final single token; and unknown or misplaced
|
||
tokens remain ordinary. Wrong-target production, same-package test, and
|
||
external-test files therefore create no imports, variants, generated-main
|
||
inputs, runtime tests, artifacts, or persistent invalidation. Names are
|
||
byte-sorted before selected-source validation, so diagnostics do not depend on
|
||
directory entry order. A recursive pattern omits a directory with no eligible
|
||
source, while an explicit wrong-target-only build rejects it as having no WW
|
||
package source. There is no source-level build-expression or user-tag mode.
|
||
|
||
Within every eligible production, same-package test, external-test, or
|
||
test-only source, the package clause is followed by one contiguous import
|
||
section and then ordinary top-level declarations. A later import is a parser
|
||
error, `imports must appear before other declarations`. The imports-only load
|
||
pass diagnoses the first import in each separated late section before graph or
|
||
producer construction; the full parser gives direct compiler input the same
|
||
result. Consequently an invalid test source creates no variant, generated main,
|
||
test binary, runtime process, accounting, retained output, or new persistent
|
||
generation. The directory command retains its existing attributable final
|
||
`FAIL\n`. Wrong-target files remain excluded before this rule and contribute no
|
||
diagnostic. This ordering state is per source and never package, import,
|
||
variant, action, artifact, publication, or persistence identity.
|
||
|
||
Every eligible source also owns an independent source-start position. An exact
|
||
UTF-8 BOM (`EF BB BF`) at byte offset zero is ignored before package-clause and
|
||
import parsing, so production, same-package, external-package, and test-only
|
||
sources all count the marker's three bytes and begin the following token at
|
||
logical line 1 column 4. The same code point anywhere else,
|
||
including a comment or literal, is a source error before variant actions,
|
||
generated main, producers, test runtime, accounting, or retained publication.
|
||
The shared coordinator applies the offset-zero rule while classifying package
|
||
clauses; the selected stage driver scans the complete source and preserves the
|
||
per-file rule while composing package units. Wrong-target files remain excluded
|
||
before either operation. The marker is source representation only and never
|
||
package/import/action/artifact/publication/persistence identity; no test result
|
||
is cached.
|
||
|
||
After filename eligibility and before package-clause classification, each raw
|
||
source byte `00` in a selected production, same-package test,
|
||
external-package test, or test-only source is one positioned
|
||
`invalid NUL character` error. Comments and literal text do not hide it. The
|
||
shared coordinator owns that early package/test rejection and reports every
|
||
raw NUL in the invalid physical source. On complete direct
|
||
frontend inputs, the C and WW source decoders diagnose each raw NUL and omit it
|
||
from their logical character streams before token recovery. Thus a NUL cannot
|
||
split an escape, identifier, number or suffix, operator, comment delimiter, or
|
||
EOF boundary into a stage-dependent second error. Test loading maintains a
|
||
stage-equal source-diagnostic stream before import discovery, graph actions,
|
||
producers, test execution, accounting, result output, or retained publication.
|
||
An invalid selected test request emits only the existing attributable
|
||
`FAIL\n`; it does not construct a variant, generated main, test child, or new
|
||
persistent generation. Wrong-target exclusion remains first, so an excluded
|
||
file with a raw NUL has no diagnostic or persistence effect. A `\\x00` escape
|
||
remains a valid literal value. This rule is limited to raw U+0000; malformed
|
||
UTF-8 and the independent per-source BOM rule retain their existing, separate
|
||
contracts.
|
||
|
||
After filename and test-role eligibility and before package-clause
|
||
classification, every malformed UTF-8 byte in a selected production,
|
||
same-package test, external-package test, or test-only source is one positioned
|
||
`invalid UTF-8 encoding` error. The shared coordinator scans selected physical
|
||
files in existing byte-sorted order and reports all malformed bytes in the
|
||
first invalid file before package grouping, import discovery, or delegated
|
||
tools. The C and WW source decoders consume each malformed byte, omit it from
|
||
their logical streams, and resume, so the byte cannot manufacture or alter a
|
||
package token, import spelling, binding, or edge or produce stage-specific
|
||
fallback recovery. Correctly encoded U+FFFD and other valid non-ASCII text in
|
||
WW's permitted comment and literal contexts remain valid. A malformed
|
||
multi-byte spelling is diagnosed byte by byte according to width-one UTF-8
|
||
decodes. Raw NUL and per-source BOM diagnostics remain independent and
|
||
interleave with malformed-byte diagnostics in physical byte order.
|
||
|
||
Malformed selected source rejects before package/test variant construction,
|
||
generated main, compiler, assembler, archiver, linker, runtime, accounting,
|
||
retention, or publication. The existing attributable explicit test request
|
||
still owns its final `FAIL\n`; no package `ok` line or test-result cache is
|
||
created. Cold rejection leaves no unit, `.wwi`, assembly, object, archive,
|
||
binary, capture, status, stage, or transaction residue. Warm rejection commits
|
||
nothing and preserves the prior generation and public output byte for byte;
|
||
restoring the valid bytes follows ordinary exact-content reuse. Producer,
|
||
runtime, publication-only, and cleanup failures are unchanged because source
|
||
rejection precedes those phases. Validation is source/request-local, adds no
|
||
process or signal boundary, cannot contaminate an overlapping valid request,
|
||
and leaves interruption and owned-process cleanup with their established
|
||
owners. Wrong-target and ordinary-build-excluded test sources remain unread by
|
||
this semantic preflight.
|
||
|
||
`malformed_utf8_is_rejected_in_every_selected_source` in
|
||
`test/package/package_test.ww`, together with focused C and WW lexer coverage,
|
||
is the focused proof owner for valid encodings and encoded U+FFFD; stray leads
|
||
and continuations; overlong, surrogate, out-of-range, truncated, repeated, and
|
||
token-boundary cases; BOM/NUL interaction; root and dependency builds; source
|
||
versus import-resolution precedence; all test roles; wrong-target exclusion;
|
||
cold and warm rejection; exact restoration/reuse; parallel isolation;
|
||
diagnostic and valid-artifact stage parity; and absence of residue. Concrete
|
||
post-change measurements and hashes are recorded only after focused and full
|
||
validation. The completed BOM, raw-NUL, and exact output-option slices are not
|
||
reopened, and canonical dotted package/import identity remains unchanged.
|
||
|
||
After that eligibility boundary and the coordinator's required package-clause
|
||
classification and production `@test` validation parses, the delegated loader
|
||
performs selected-basename Go 1.26.5 simple-fold preflight before its graph
|
||
import scan. During graph loading, effective canonical imports register only
|
||
after contextual local/vendor expansion; exact identity reuse is accepted, but
|
||
two distinct fold-equivalent identities reject the entire shared plan.
|
||
Selected basenames register in one canonical-directory scope. A production
|
||
build registers production names only. A test plan shares the filename scope
|
||
across production, internal-test, and external-test actions, including
|
||
same-only, external-only, and mixed directories, without combining their source
|
||
units. Hidden, underscore-prefixed, wrong-platform, and otherwise ineligible
|
||
files never register. Package variants, product-scoped recompiled copies,
|
||
support, and generated main remain action wiring over exact identities and do
|
||
not manufacture package collisions. The fold preflight does not replace or
|
||
precede those coordinator-owned source-validation parses.
|
||
|
||
Separate compilation is the only driver build path; no compatibility mode
|
||
switch remains.
|
||
|
||
`test/package/package_test.ww` owns the focused dual-stage
|
||
`single_root_build_output_directory` observer. It covers existing and missing
|
||
directory spellings; trailing and non-trailing forms; literal, logical,
|
||
default-dot, symlink, raw-file, and implicit-default routes; build/test
|
||
adjacency; mixed and repeated roots; command-only publication, no-main and
|
||
implicit-collision rejection, non-main default behavior; import
|
||
diagnostic precedence over no-main, derived-path, duplicate-destination, and
|
||
recursive implicit-collision checks; `-S -w` command selection with long,
|
||
duplicate, implicit, and missing-directory publication preflight omitted;
|
||
cold, warm, and invalidated persistence;
|
||
compiler, assembler, and linker action traces; compiler/linker failure and
|
||
linker signal; prior-state and directory-creation rollback; concurrent
|
||
isolation; executable modes and runtime exit values; `.new`/transaction
|
||
cleanup; and Cstage/WWstage diagnostic, binary, assembly, and persistent
|
||
semantic-artifact byte parity. General output permissions, occupied stages,
|
||
multi-product transactions, null discard, and test runtime timeout remain with
|
||
their existing observers.
|
||
|
||
`test/package/package_test.ww` also owns the dual-stage
|
||
`declared_name_identity_and_file_import_scope` and
|
||
`explicit_import_alias_binding_modes` observers. They generate temporary
|
||
directory trees proving that canonical import identity, physical directory,
|
||
declared package name, optional source alias, and effective source-file
|
||
qualifier remain distinct. The alias matrix covers default and explicit-only
|
||
qualification, bare function/type/def/const/variable rejection with exact
|
||
unused-before-undefined diagnostics, same-file duplicate bindings, accepted
|
||
same-path imports under distinct bindings, alias reuse across files, sibling
|
||
scope isolation, package-declaration collisions, unused aliases, blank
|
||
side-effect imports, repeated blank/default/explicit combinations, and blank
|
||
no-binding/no-unused behavior. It also pins canonical `.wwi` spelling,
|
||
archive/action ownership, one canonical direct edge for repeated occurrences,
|
||
stage-equal diagnostics and binaries, and clean rejection state.
|
||
The declared-name observer proves imports are file-scoped while dependency
|
||
edges are the package-wide sorted union; command and
|
||
production/internal/external/directory-main actions retain canonical action
|
||
ownership while one canonical directory owns their product; external
|
||
self-imports bind the augmented internal action; vendor expansion changes
|
||
identity but not the effective qualifier;
|
||
compiler argv contains only direct `.wwi` inputs; and its named rejected
|
||
actions leave neither committed nor staged action artifacts or a published
|
||
binary. It also forces a request transaction to reject after dependency work
|
||
has staged, then proves that both stages restore every prior artifact, unit,
|
||
tool record, stamp, and product rather than accepting a mixed warm generation.
|
||
Together with the existing directory, recursive, vendor,
|
||
exact-argv, command, and persistent-workdir observers, the package suite proves
|
||
archive-only link argv and exact warm/rejection-state behavior without
|
||
duplicating those broader mechanisms in this observer.
|
||
|
||
The focused dual-stage `bare_import_bindings_require_selectors` observer is the
|
||
acceptance owner for the rule that an effective default or explicit import
|
||
binding is a file-local package-name object, not a value or type. Its generated
|
||
matrix must prove exact `use of package BINDING not in selector` value
|
||
diagnostics and `BINDING (package name) is not a type` type diagnostics; an
|
||
unused diagnostic for every named binding that has only bare occurrences; and
|
||
the absence of that unused diagnostic once a legal selector independently uses
|
||
the binding. It must cover occurrence order, repeated bare occurrences,
|
||
explicit aliases, builtin-spelled bindings including `len`, `size`, and `align`,
|
||
qualified value and type controls, nested value and type contexts, sibling-file
|
||
isolation, blank imports, rejected `init` bindings, and missing-target
|
||
precedence. Type-shaped arguments parsed for `size` and `align` must retain type
|
||
checking when either spelling is instead an import binding; neither stage may
|
||
fall into an internal expression-kind diagnostic.
|
||
|
||
The adjacent focused dual-stage
|
||
`lexical_import_bindings_shadow_normally` package observer, together with the
|
||
tool-suite `paramshadow_lexical_bindings` fixture matrix, is the acceptance
|
||
owner for ordinary lexical shadowing of an effective file-local package-name
|
||
object. Together they require a selector before a later local to resolve to and
|
||
consume the import, while the later spelling resolves to the closer parameter,
|
||
`let`, tuple-let, ordinary-`for`/range, or match-arm binding. Nested blocks and
|
||
loop exit restore the import; a parameter wins throughout its body;
|
||
self-shadowing initializers retain the outer import until the local declaration
|
||
point; and every annotated tuple type is checked before any tuple binder enters
|
||
scope. Default, explicit, and builtin-spelled qualifiers follow the same rule.
|
||
A local value, struct or pseudo-field, function-pointer field, or local
|
||
enum/member collision must use the local receiver rather than recover the
|
||
same-spelled import. Conversely, a shadowed dotted type or invalid scalar
|
||
selector must reject as a local use without a checker/backend cascade. A
|
||
selector-shaped local-only occurrence does not consume the import, so its
|
||
unused diagnostic retains source-position precedence. Sibling source files
|
||
retain independent import bindings and a separately selected legal import use
|
||
remains effective. Blank, effective-`init`, and missing-target controls remain
|
||
owned by their immediately adjacent focused observers and are explicit
|
||
non-effects of this acceptance pair.
|
||
|
||
This observer exercises raw-source and directory builds, imported dependencies,
|
||
production reached by tests, same-package, external-test, and honest
|
||
test-only sources, filtered execution, retained test execution, and later
|
||
direct retained-binary execution. Cstage and WWstage must agree on status,
|
||
stdout, normalized full stderr (including positioned diagnostic order) for
|
||
build and test rejection, representative comparable semantic artifacts, every
|
||
test role's public binary bytes, retained binary bytes, and valid runtime
|
||
results. Its lifecycle matrix requires cold invalid requests to leave no public
|
||
or retained product and an empty workdir; a warm valid-to-invalid unused-import
|
||
transition whose source also contains an invalid local selector to preserve the
|
||
prior public product and complete committed generation byte-for-byte; and
|
||
restoration to recover ordinary exact-byte reuse with no `.new`, `.install`,
|
||
`.wwtxn.*`, adjacent `.sepwork`, capture/result, or request-scratch residue. The
|
||
rule changes neither source eligibility,
|
||
package/import identity, direct graph edges, action/variant identity, init
|
||
ordering, test process/state/fatal-abort topology, runtime/process ownership,
|
||
publication transaction shape, persistence format, concurrency isolation,
|
||
interruption handling, nor descendant cleanup; those boundaries retain their
|
||
existing owners. Go has no range-loop `else` clause; that WW-only extension's
|
||
pre-existing Cstage/WWstage scope difference is explicitly outside this
|
||
pinned-Go observer, and each import-use prepass continues to mirror its own
|
||
stage's live checker there.
|
||
|
||
The `bare_import_bindings_require_selectors` observer must exercise ordinary
|
||
root and imported builds plus
|
||
production, same-package test, external-test, and honest test-only source
|
||
roles. Cstage and WWstage must agree on status and normalized stdout/stderr,
|
||
including diagnostic order and source position, and valid controls must produce
|
||
byte-identical comparable artifacts and equal runtime results. Its lifecycle
|
||
matrix must include cold rejection with no public or retained product, warm
|
||
preservation of every prior committed work-file and public byte, imported
|
||
dependency failure, invalidation followed by rejection, subsequent valid
|
||
recovery, and exact transaction-residue checks. Legal selector controls retain
|
||
ordinary graph/action, compilation, linking, publication, persistence, and
|
||
reuse behavior. Producer/runtime failure, concurrency, interruption, process
|
||
topology, and descendant cleanup remain with their established observers
|
||
because this checker-owned rejection creates no producer or runtime boundary.
|
||
|
||
The focused dual-stage `effective_init_imports_never_enter_binding_recovery`
|
||
observer is
|
||
the acceptance owner for imports whose effective file-local qualifier is
|
||
`init`. Its validation matrix is required to cover an explicit alias and an
|
||
implicit qualifier obtained from `package init`; unused and used occurrences;
|
||
repeated rejected occurrences; a package-scope declaration named `init`;
|
||
later `init.Name` recovery; missing-target precedence; and valid blank and
|
||
non-`init` explicit-alias controls. It must exercise ordinary root and imported
|
||
builds plus production-test, same-package-test, external-test, and test-only
|
||
source roles where applicable. Each resolved rejected occurrence must produce
|
||
one core diagnostic at the alias/path spec token and no unused, duplicate, or
|
||
declaration-collision noise from that binding; a later selector remains an
|
||
independent undefined-name error. The resolved dotted occurrence must remain
|
||
in dependency graph and action provenance while the rejected qualifier stays
|
||
absent from file scope.
|
||
|
||
That observer's lifecycle proof requires fixed-path Cstage/WWstage status,
|
||
stdout, and stderr parity; cold absence of public and retained products; warm
|
||
preservation of the complete committed work-file manifest and public product;
|
||
imported-dependency rejection and cold empty-workdir rollback; valid control
|
||
artifact-byte parity; and absence of active `.new`, `.install`, `.wwtxn.*`,
|
||
adjacent `.sepwork`, capture, scratch, and tool-stage transaction residue.
|
||
Producer/runtime failure, request concurrency, interruption, descendant
|
||
cleanup, and test-process topology retain their established owners because
|
||
the selected checker rejection adds no producer, runtime, process, signal,
|
||
timeout, shared-state, or publication boundary. The observer passed in both
|
||
stages, including imported-dependency rejection, all four test-source roles,
|
||
cold and warm rollback, normalized diagnostic parity, valid artifact-byte
|
||
parity, and residue checks. The complete ordered `test`, `test-commit`,
|
||
`test-byteid`, `test-bootstrap`, `test-platform`, and `test-all` gates also
|
||
passed. Build workdir format remains 18, test workdir format remains 19,
|
||
semantic storage remains 3, and no test-result cache is introduced.
|
||
|
||
The same package owner contains the focused
|
||
`directory_test_execution_working_directory` observer. It constructs
|
||
independent temporary directories from an unrelated caller cwd and compares
|
||
Cstage/WWstage output for production/internal/external/combined and every
|
||
test-only shape; production and test-only dependency initialization;
|
||
recompiled external self-import; duplicate inherited `PWD`; absent, empty,
|
||
nonempty, and duplicate inherited `PATH`; ordinary data,
|
||
`testdata`, relative writes, and deliberately nonempty caller stdin;
|
||
direct/recursive/redundant/absolute/symlink roots; reversed request and creation
|
||
order; serial and parallel products; filters, list, and no-match execution;
|
||
failure and timeout; build/no-test and compile-only paths; running retained
|
||
success and failed-run rollback; direct published binaries and raw single-file
|
||
execution; build-tool cwd/argv/environment/stdin;
|
||
persistent data-only reuse and artifact bytes; input-open failure before capture
|
||
creation; source-class rejection with empty workdirs; and deterministic
|
||
post-build child-`chdir` failure isolated from a successful sibling. It pads the
|
||
inherited environment beyond former fixed observer sizes, requires one appended
|
||
product `PWD`, one toolchain-first child `PATH`, requires EOF for captured
|
||
actions and caller data for inherited-
|
||
stdio routes, alternates fd-1/fd-2 write syscalls through every executing
|
||
variant and initializer, requires one ordered stdout stream on success,
|
||
assertion failure, signal, timeout, and setup failure, requires direct/raw
|
||
inherited routes to keep their streams separate, and sweeps the persistent
|
||
workdir for staged residue.
|
||
Command-global bounded-memory failure remains independently
|
||
owned by `allocation_failure_is_command_global`.
|
||
|
||
The focused `directory_test_trailer_starts_on_new_line` observer generates
|
||
empty, already terminated, and unterminated combined captures. Across both
|
||
stages it covers stdout success, stderr failure, signal termination,
|
||
concurrent products, filtering, listing, running retention, retained artifact
|
||
bytes, and the raw/manual routes that have no coordinator trailer. It requires
|
||
complete concurrent stdout/stderr parity and forbids both an adjacent trailer
|
||
and a doubled separator.
|
||
|
||
The same package owner contains the focused
|
||
`platform_filename_source_selection` observer. It independently generates the
|
||
suffix matrix, production/internal/external sources, wrong-target import and
|
||
malformed sentinels, wrong-target-only directories, and reverse-created
|
||
diagnostic files. Across cold and persistent Cstage/WWstage roots it compares
|
||
normalized compiler/assembler/linker argv, units, `.wwi`, assembly, objects,
|
||
archives, generated-main archives, binaries, runtime/test output, direct and
|
||
recursive behavior, reversed roots, ignored-edit reuse, selected private-change
|
||
propagation, and request rollback after a dependency has staged and the root
|
||
compiler fails. Wrong-target test files cannot add a target to the directory
|
||
main or create one for an otherwise no-test directory. The bounded-memory
|
||
package-initialization observer now pressures the combined directory topology
|
||
itself: production, augmented internal test, external self-import, a transitive
|
||
recompile-for-test clone, support, and the two-target generated main. Each stage
|
||
searches its own bounded address-space ceiling, while the accepted failure must
|
||
have the same `ww: out of memory` diagnostic, invoke no compiler, assembler, or
|
||
linker, and leave an empty caller work directory with no output, status, or
|
||
staging path.
|
||
|
||
The same observer now owns selected-basename folding: ASCII production,
|
||
internal, external, same-only, external-only, mixed, and cross-classification
|
||
collisions; printable Unicode Kelvin folding; malformed UTF-8 replacement-rune
|
||
keys with exact `\xNN` diagnostics; accepted composed/decomposed neighbors;
|
||
ordinary-build isolation from test collisions; ignored folded pairs; reversed
|
||
creation order; and direct/recursive collision-diagnostic parity. It proves zero
|
||
compiler/assembler/linker calls and an empty workdir, including no
|
||
test-support/main artifact, on cold rejection. A committed warm package then
|
||
gains and loses a colliding file; the failed middle request preserves every
|
||
unit, `.wwi`, assembly, object, archive, binary, tool record, and stamp, and
|
||
removal restores exact reuse.
|
||
`package_graph_diagnostics_are_stable` provides the corresponding direct,
|
||
transitive, reversed-root, recursive, same-directory, exact-repeat, and warm
|
||
import proof. `vendor_directory_import_resolution` proves folding uses the
|
||
expanded vendor identity under reversed imports and product descriptors, even
|
||
when both spellings reach one physical directory, and that multi-product
|
||
rejection publishes no output, status, tool state, or staging residue.
|
||
|
||
`test/sep/sepinit_test.ww` is the single focused package-initialization owner.
|
||
It generates all source trees temporarily and runs independent cold/persistent
|
||
Cstage and WWstage legs. Its matrix covers blank-only reachability; dependency,
|
||
diamond, and independent ready-task order; runtime call/allocation and aggregate
|
||
package lets; multiple init declarations and invalid forms; direct/qualified
|
||
init invisibility; initialization cycles and diagnostic order; command,
|
||
internal-test, external-test, support, and one directory-generated-main
|
||
ownership; canonical
|
||
task and dispatcher symbols; deterministic one- and two-member archives;
|
||
`.wwi` exclusion; byte-identical artifacts/binaries; init-only invalidation;
|
||
warm invalid-init rollback; direct/recursive variant equivalence; exact
|
||
production, support, ptest-before-pxtest-before-main task ordering, exactly-once
|
||
package/dependency initialization in one dispatcher; complete normalized
|
||
rejection diagnostics; dangling staging/rollback no-follow rejection; and
|
||
checked compiler-output failure/non-regular-destination rollback; and
|
||
bounded-memory Cstage/WWstage allocation-failure parity across the complete
|
||
combined package-test graph, under independently discovered ceilings supplied
|
||
by the repository-built `sep-limitexec` helper.
|
||
|
||
`ww build` and an explicit single-file `ww test -o <stem>` publish
|
||
`<stem>.sepwork` as a caller-owned artifact directory. The driver acquires it
|
||
with one fresh `mkdir` and refuses an existing path; it never clears a
|
||
collision. A caller keeps only the exact artifacts it observes and removes
|
||
that exact tree on every later success or failure. Directory-package test
|
||
plans instead keep their cold semantic-action scratch and runnable binary
|
||
inside the coordinator's temporary root; a compile-only retained executable
|
||
escapes through the build transaction, while a running retained executable
|
||
uses the post-run install action above. `ww run` and no-output single-file
|
||
`ww test` use driver-owned scratch instead; both driver stages place that
|
||
scratch and their temporary executable beneath one freshly acquired directory,
|
||
remove both after every build result, and make cleanup failure fail the
|
||
command. Make recipes build driver-produced tools in invocation-owned
|
||
directories and apply the same exact cleanup rule.
|
||
|
||
`ww build -w DIR` and single-file `ww test -w DIR` replace that scratch with a
|
||
caller-owned persistent package-artifact workdir: for these direct routes the
|
||
directory must already exist, is never cleaned by the driver, and holds one
|
||
committed unit, `.wwi`, `.s`, `.o`, and dep `.a` per package plus byte copies of
|
||
the invoking driver, compiler, and assembler and a small mode stamp. A package
|
||
is reused only when
|
||
its freshly composed owner unit byte-equals the committed unit, no recompiled
|
||
direct dependency emitted changed export bytes, and every applicable recorded
|
||
executable byte-equals the live executable — content identity only, no mtimes,
|
||
no hashes, every decision reproducible with `cmp` against plain files. The
|
||
driver identity covers graph construction, owner-unit composition,
|
||
direct-export argument construction, archive creation, and commit algorithms
|
||
that neither unit bytes nor compiler identity can name.
|
||
Recompiled artifacts, dispatcher artifacts, products, statuses, tool copies,
|
||
and the stamp land at staged `.new` names. After every requested product stages
|
||
successfully, one rollback-capable transaction installs the whole generation;
|
||
any producer or installation failure preserves the prior committed bytes and
|
||
removes remaining stages. An interrupted or rejected request therefore cannot
|
||
create false reuse or a mixed generation; a successful executable link still
|
||
reruns when required. One workdir serves one invocation at a time and may hold
|
||
the complete command-global action universe for all selected roots and isolated
|
||
variants; semantic identity, rather than request shape, controls reuse. Both
|
||
driver stages implement the identical contract. Test-mode persistent workdirs
|
||
use format 19. This is build staleness in the
|
||
Make/mk/Go sense, not a result cache:
|
||
real directory test products always run, while no-selected-test directories do
|
||
not create a process. The byte-identity and bootstrap gates keep building on
|
||
fresh scratch. `make clean` reclaims every workdir under `out/`.
|
||
|
||
Directory-product cwd, `PWD`, and test `PATH` are request-time child-process
|
||
metadata, not persisted action inputs or results. A runtime directory-entry
|
||
failure therefore does not erase a successfully committed compilation
|
||
generation. Changing only ordinary fixture data causes no
|
||
unit/export/assembly/object/archive/main/binary change and no producer work
|
||
beyond the same established warm final relink,
|
||
while the next always-run product observes the new bytes. Build workdir format
|
||
remains 18, test workdir format remains 19, and semantic storage remains 3.
|
||
|
||
Fold keys and first-spelling tables are request-only loader state and are never
|
||
stored in a workdir. They do not alter successful unit bytes, action/storage
|
||
keys, or tool records, so build format 18, test format 19, and semantic storage
|
||
format 3 remain unchanged. Structural fold rejection occurs before staging and
|
||
cannot mutate a committed generation; a later request with the collision
|
||
removed evaluates the original exact-key reuse contract.
|
||
|
||
On a package or tree target, `ww build/test -w DIR` forwards that exact caller
|
||
path as the one command-global semantic-action store; neither pattern spelling
|
||
nor package-group name derives a persistent subdirectory. The delegated driver
|
||
may create a missing store only after graph and request preflight, and rolls
|
||
back newly created empty prefixes if later setup fails. Every reuse decision
|
||
stays with the driver's content-identity contract above. Test `-c` may use the
|
||
same store: the workdir owns semantic actions and the invocation/output path
|
||
owns the separately staged retained executable. The `test-library` route uses
|
||
the same command-global store contract: one `ww test -j $(JOBS) -w
|
||
out/wwbuild/wwtest-lib lib/...` line owns library behavior (measured: 2.3s
|
||
cold, 1.0s warm at
|
||
`-j 4`, vs 4.7s for the retired 59-target per-file fan-out).
|
||
|
||
`test/lang` currently uses one package per source file, so its complete gate
|
||
still performs independent package builds. That remaining source layout is not
|
||
hidden behind caching or concurrency; it is outside the small `test` target.
|
||
|
||
## Compiler-only byte identity
|
||
|
||
`ww build -S` and `ww test -S -o <stem>` run source discovery, dependency
|
||
ordering, unit composition, and each required `w6c -c` invocation. They return
|
||
after the complete `.s`/`.wwi` set exists. The producer loop does not invoke
|
||
`w6a`, create per-package archives, or invoke `w6l` when `-S` is active.
|
||
|
||
`test-lang-byteid` runs the 158 selected language files once with C `w6c` and
|
||
once with WW `w6c`, requires identical emitted `.s` filename sets including
|
||
`__root.s`, and compares those bytes. Relative to the old two-leg full builds,
|
||
this removes at least 3,476 assembler launches, 3,160 archive writes, and 316
|
||
linker launches from the comparison loop. A cold Make invocation may still
|
||
build prerequisite compiler binaries; the compiler-only claim applies to the
|
||
per-language-file comparison path.
|
||
|
||
`test-data-byteid` applies the same comparator to the declarative corpus:
|
||
every non-error `case.ww` builds twice through the fixed cstage driver with
|
||
only `WW_W6C` swapped, and every emitted per-package `.s` must be
|
||
byte-identical. `//ww:error` fixtures have no `.s`; their both-stage reject
|
||
parity is owned by the fixture corpus itself. Known cs/ww divergences are
|
||
pinned in `DATABYTEID_DIVERGED` with the `989_lib_byteid` discipline: a
|
||
pinned fixture must still build on both stages and still differ, so a
|
||
compiler fix fails the gate demanding graduation rather than silently
|
||
widening coverage. The full sweep compares the 1,157 non-error fixtures
|
||
in about a minute and is scratch-rooted under `out/`, not `/tmp`.
|
||
|
||
Byte identity is an explicit proof gate. It is not a prerequisite of `test` or
|
||
`test-commit`.
|
||
|
||
## Bootstrap, subprocesses, and CSP
|
||
|
||
Stage-2-through-stage-4 fixed-point proofs and the 950/991–995 self-host gates
|
||
are reachable through `test-bootstrap` and `test-all`, never through `test` or
|
||
`test-commit`. Cold ordinary targets may still build their C- and WW-stage tool
|
||
prerequisites once; they do not iterate those tools to a fixed point. The C
|
||
bootstrap source and the standalone `nocc` route remain intact.
|
||
|
||
The bootstrap recipe owns the fixed `out/bootstrap` tree. Make schedules that
|
||
target once within one invocation, but two independent `make bootstrap`
|
||
invocations are not safe to run concurrently and remain mutually exclusive.
|
||
|
||
`lib/os/exec` is the sole reusable WW subprocess mechanism. Fixture and package
|
||
coordinators use its captured asynchronous path. An empty captured-command
|
||
`stdinpath` opens the null device; an explicit path supplies controlled input,
|
||
and either descriptor is installed before exec with checked setup reporting.
|
||
Distinct output paths create independent exclusive captures; byte-equal output
|
||
paths open once and duplicate that descriptor so fd 1 and fd 2 share the same
|
||
open file description. The executor process proof covers both modes, including
|
||
closed caller standard descriptors.
|
||
The WW driver directly uses `os.exec.runstdio` for inherited-stdio,
|
||
inherited-environment, leader-only compiler, assembler, linker, cleanup, run,
|
||
and single-file-test calls. The local WW `procrun` implementation is deleted.
|
||
The C bootstrap retains its C process implementation because it cannot consume
|
||
a WW standard-library module.
|
||
|
||
WW has tokens and an opaque type for future CSP/channel work, but no mature
|
||
production channel operations, task runtime, or scheduler. No channel,
|
||
goroutine, thread, worker-runtime, or CSP library was added. Coordinators stay
|
||
single-threaded; OS process polling does not require language-level threads.
|
||
|
||
## Retired mechanisms
|
||
|
||
The following are deleted, not adapted:
|
||
|
||
- `test/run`, including its phase classifier, `xargs` scheduler, atomic private
|
||
records, timeout-text classifier, result collector, and last-green cache;
|
||
- `test/run_test.sh`, the synthetic shell tests for that protocol;
|
||
- every explicit `TESTS` registration and all 329 explicit wrapper rules;
|
||
- the unregistered `test/runww.ww` corpus runner;
|
||
- frozen duplicate compiler-corpus code under `internal/wwtest`, `test/wwtest`,
|
||
and `test/compiler`;
|
||
- the redundant standalone `smoke`, `test-run`, and `test-harness` routes; and
|
||
- library-launcher wrappers whose only assertion was an existing `@test`
|
||
source's exit status, including the declarative `900_stdlib.c` launcher.
|
||
|
||
There is no test cache, daemon, scanner, generated manifest, database, new
|
||
framework, compatibility API, concurrency runtime, dependency, or changed
|
||
timeout policy in this architecture.
|
||
|
||
## Open driver work
|
||
|
||
Directory-package `-c` and `-o` have the applicable Go 1.26.5 retention,
|
||
naming, fan-out, execution, and publication behavior. Direct external SIGTERM
|
||
of either driver during blocked persistent compilation remains open: prior
|
||
public and committed semantic bytes survive, but the directly spawned compiler
|
||
can survive with three fixed-name `.new` stages, and a later persistent request
|
||
then rejects the existing `.unit.new`. The required repair is driver-owned
|
||
child-process-group supervision and normal request rollback before re-raising
|
||
the original signal; blind removal of `.new` files cannot distinguish foreign
|
||
or concurrent stages.
|
||
|
||
## Validation policy
|
||
|
||
Use `test-unit` as the inner loop for lexer, parser, checker, and narrow codegen
|
||
changes. Run `test` for the ordinary local compiler check, followed by the
|
||
focused owner for the changed behavior. Use `test-commit` for ordinary
|
||
pre-commit behavior; use `make -j4 JOBS=4 test-commit` when parallel feedback is
|
||
desired, and `make -j1 JOBS=1 ...` to reproduce failures deterministically.
|
||
Run `test-byteid` and `test-bootstrap` only when those proof categories are
|
||
intended. `test-all` is the exhaustive CI/release composition and should not be
|
||
launched casually.
|