# WW package, dependency, build, and bootstrap architecture Status: **binding architecture decision** Decision date: 2026-08-10 Implementation status: specified, not yet implemented This document selects the production architecture that replaces WW's current package driver, source-like interface protocol, work-directory reuse scheme, Make orchestration, test coordinator, and bootstrap chain. It is a greenfield decision. Migration effort is recorded only to plan implementation; it did not influence the selection. The words **MUST**, **MUST NOT**, **SHOULD**, and **MAY** are normative. ## 1. Executive decision WW will have one integrated command backed by one typed, content-addressed action graph. Language imports describe the language-package subgraph. A small, declarative `ww.mod` file describes only facts that source imports cannot: distribution requirements, products, generated inputs, native providers, and unusual link steps. Both descriptions lower to the same graph, scheduler, sandbox, cache, and explanation machinery. There is no general build language and no arbitrary build script. A one-directory, zero-dependency executable needs no manifest. Distributed projects use an exact lock file; fetching and updating are explicit commands, while build, run, test, documentation, and installation never access the network or rewrite project metadata. Packages produce target-specific binary export data and one object, importers consume only direct export data, and final products link a declared ordered closure. Every cached action names its compiler, target, profile, tools, sysroot, runtime, native inputs, environment, and content. The official toolchain owns these protocols and ships a pinned tool closure, but WW does not permanently own an assembler or linker. The decisive insight is that **the package graph and the build graph are not the same graph**. Imports are a complete and desirable description of WW-language dependencies. They cannot honestly describe a C header tree, a host generator, an assembler, a linker script, a CRT, or a sysroot. Making imports pretend to do so hides native inputs; making every project use a programmable build framework destroys the simple ordinary path. Two small declarative front ends lowering to one action engine are simpler as a system than either lie. The architecture is named **WW Action Build** in this document. That is a label, not another user-facing product: the command remains `ww`. ### 1.1 The Pike lens and attribution Pike explicitly documented and defended these Go design choices and principles: - language-defined imports make dependencies explicit, clear, and mechanically computable; - unused imports and import cycles are errors; rejecting cycles improves package boundaries and independent maintenance; - compilation speed and short edit/build cycles are primary design properties; - a direct dependency's compiled artifact can carry the deeper public type facts needed by its clients, so an importer opens only direct dependency artifacts; and - orthogonal, predictable concepts, fewer ways to express a construct, and a simple user experience are worth substantial implementation work. Those points are stated in Pike's 2009 Go talk, the 2012 SPLASH article, and his 2015 simplicity talk ([2009 talk](https://go.dev/talks/2009/go_talk-20091030.pdf), [2012 article](https://go.dev/talks/2012/splash.article), [Simplicity is Complicated](https://go.dev/talks/2015/simplicity-is-complicated.slide)). The collective Plan 9 papers add system-wide placement of complexity, focused interfaces, and transparent text or explicitly encoded binary data. `Go in Go` documents one contingent case in which owning more of the toolchain simplified Go; it does not establish permanent toolchain ownership as a general Pike principle ([Go in Go](https://go.dev/talks/2015/gogo.slide)). Plan 9's `mk` constructs the dependency graph before execution, rejects cycles and ambiguous recipes, and schedules independent work in parallel. Plan 9 used a target-specific compiler/assembler/loader family and portably encoded target object conventions ([mk](https://9p.io/sys/doc/mk.html), [mkfiles](https://9p.io/sys/doc/mkfiles.html), [compilers](https://9p.io/sys/doc/comp.html)). Modern module-path/version semantics, Minimal Version Selection, `go.sum`, the modern Go build cache, automatic toolchain selection, and current supply-chain policy are later Go-team designs, not principles uniquely attributable to Pike ([module reference](https://go.dev/ref/mod), [`go` command](https://go.dev/cmd/go/), [toolchain selection](https://go.dev/doc/toolchain), [toolchain rebuilding](https://go.dev/blog/rebuild), [supply-chain policy](https://go.dev/blog/supply-chain)). This decision borrows some invariants from those systems but does not attribute them to Pike. The following are this document's inferences from the documented principles: - strict directory packages and direct binary export data are the smallest way to keep dependencies computable and compilation fast; - a declarative native/action layer is necessary for an unmanaged language, because omitting it moves complexity into ambient shell state; - one shared action engine is simpler than independent language and outer-build caches; - given WW's complete-graph, frozen-build, and explainable-key hard gates, arbitrary graph-producing programs are rejected; they would require executing dependency host code before the graph is inspectable and add another permanent user programming model; and - WW should specify a toolchain closure but should not maintain an assembler and linker forever when pinned external tools make the whole system smaller. Modern native requirements force deliberate departures from historical Plan 9 and early Go: cryptographic source identities, lock files, explicit build/host/ target separation, sysroot and SDK identity, hostile dependency acquisition, cross-platform sandboxes, and cache-miss explanations were not their complete problem statement. WW adopts their architectural restraint, not their ambient host assumptions. ### 1.2 What follows from being unmanaged and native Being unmanaged/native genuinely requires the build model to know: - the target data layout and C ABI; - foreign symbol spelling and visibility; - object format, relocation model, CPU features, and assembly dialect; - ordered objects, archives, shared libraries, linker scripts, and archive-group semantics; - the libc, CRT, dynamic loader, SDK, runtime, and sysroot closure; - freestanding entry and runtime policy; - build-machine tools that generate host- or target-machine inputs; and - ABI compatibility among compiler, runtime, native providers, and final link. It does **not** follow that WW needs multiple dependency versions, semantic version ranges, a network resolver in every build, programmable build scripts, feature unification, a global namespace, or its own linker. In particular, the absence of a garbage collector says nothing about version resolution. ### 1.3 Binding answers to the critical questions | Question | Binding answer | |---|---| | Package identity | One canonical import path: the owning module identity for its root package, otherwise that identity plus `/` and the normalized package-relative path. The declared package name is a source qualifier, not identity. | | Identity versus location/origin/version/content | All are separate. A resolver record maps identity and selected version to an origin and source-tree digest; a workspace maps identity to a local location. | | Directory membership | Exactly one package per directory. Immediate selected source files belong to it. Nested directories never do. | | Single-file packages | Deleted. A one-file directory package remains configuration-free. | | Language dependency graph | The compiler-parsed imports alone define it. Manifest native/action edges extend the build graph, never the language graph. | | Import interfaces | Direct dependencies only. Each direct `.wwe` contains the deep public type information needed to understand its own API. | | `.wwi` | Deleted and replaced by deterministic, versioned binary `.wwe` export data. Canonical source prototypes are not an interchange format. | | Package invalidation | The package action key changes when its selected own sources/generated inputs, direct export digests, compiler/toolchain, target/profile, declared environment, or protocol changes. A private transitive change does not invalidate it. | | Cache key | Domain-separated SHA-256 over the canonical action record defined in section 6.6. | | Cache scope | A per-user global local content store plus a project-local graph-history index. Remote import/export is explicit, never part of ordinary build. | | Corruption/upgrades | Every object is rehashed on read; corrupt entries are quarantined. Tools and protocol versions are content inputs, so upgrades change keys. | | Multiple versions | One selected version of a module identity. Incompatible major releases use distinct module identities ending `/vN`, so those identities may coexist. | | Build scripts | Arbitrary scripts are forbidden. A finite declarative action may run a pinned build-machine tool in a denied-by-default sandbox. | | Action authority | Exact readable inputs, writable outputs, argv, environment, execution platform, and tool closure. No network, shell, ambient `PATH`, clock, randomness, or undeclared filesystem access. | | Acquisition | `add`, `update`, `lock`, `fetch`, `toolchain fetch`, cache transfer, and explicitly authorized remote observation may use the network. Artifact build/analysis and ordinary tests may not; running the finished user program is outside acquisition. | | Manifest for a trivial program | No. A standalone directory containing a `main` package is sufficient. A manifest is required for distribution dependencies, multiple products, native providers, or generated inputs. | | Configuration placement | Imports in source; identity, requirements, products, native declarations, and actions in `ww.mod`; exact selected closure in `ww.lock`; local paths in `ww.work`; ephemeral target/profile/output choices on the command line. | | Local overrides | `ww.work` maps a module identity to a local source tree and records its observed digest. Imports do not change. | | Target-specific files | A fixed filename-suffix selection rule; no source-level build expressions and no user-programmable selector. | | OS distribution | A distributor may vendor the locked source closure or supply an exact `ww.work`/native-provider map. Substituted files and tools get new digests; frozen mode never silently consults the host. | | Reproduction input | For supported official targets: project source, complete locked dependency-source bytes (vendor/CAS export), `ww.lock`, named immutable toolchain bundle, target/profile, and every declared external seed/signing input. Hashes without bytes are insufficient. Impure profiles forfeit the promise. | | Assembler/linker ownership | No permanent ownership. The toolchain descriptor pins complete implementations. The current WW tools may bridge migration only. | | Stage zero | One release-generated, checked-in portable C99 compiler snapshot plus a tiny declarative bootstrap plan and digest file. | ### 1.4 Corrective protocol boundary (2026-08-11) The first Phase 0 experiment over-scoped the protocol freeze. It turned package resolution, manifest parsing, compiler projections, action lowering, provider recursion, graph traversal, scheduling, cache policy, failure precedence, and bootstrap assertions into a declarative expression language. Its checker then implemented those operations again. That experiment is preserved as recoverable migration evidence, but it is not the production architecture. The correction follows the separation visible in the pinned Go source. Go reads imports from source with an imports-only parse and resolves them in ordinary loader code ([`go/build/read.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/go/build/read.go#272), [`cmd/go/internal/load/pkg.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/pkg.go#1775)). The compiler writes a narrow export representation in compiler code ([`cmd/compile/internal/noder/writer.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/compile/internal/noder/writer.go)), while `cmd/go` builds and schedules an in-memory action graph with ordinary Go functions ([`work/action.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/action.go#85), [`work/exec.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/exec.go#73)). Action IDs and cache storage/validation are executable hashing and storage operations, not schema programs ([`work.buildActionID`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/exec.go#260), [`internal/cache`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/cache/cache.go#95)). Go's `cmd/dist` performs concrete staged builds and checks that the final targets are not stale. Separate compiler reproducibility tests compare repeated outputs byte-for-byte, while the release process independently rebuilds and compares archives bit-for-bit ([`cmd/dist/build.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/dist/build.go#1404), [`reproduciblebuilds_test.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/compile/internal/test/reproduciblebuilds_test.go), [`rebuild` account](https://go.dev/blog/rebuild)). WW adopts that division, not Go's module/network/toolchain policy. Normal typed C/WW code MUST own source loading, parsing, resolution, compiler behavior, lowering, orchestration, storage, and bootstrap execution. Declarative schemas MUST describe wire representation only. Tests MUST verify executable behavior; a schema or proof-shaped record MUST NOT stand in for running it. A generator is permitted only for repetitive codec data and MUST be small, generic, deterministic, and byte-for-byte reproducible. Phase 0 therefore freezes only WWAR framing and primitive canonical encoding; record/enum/union tags, field order, encoded defaults and record kinds; exact domain-separated digest and action-key byte formulas; compact positive and malformed-wire vectors; a small reference codec; deterministic data-only codec generation; and its repository gate. It does not freeze algorithms for deriving the represented records. Every declared record tag remains encoded, including an optional field's empty `encoded_default`; absence is not default insertion. The owning implementation phases are binding: | Behavior removed from the Phase 0 experiment | Owning phase | |---|---| | source imports, package graph/cycles, `.wwe`/`.wwlm`, compiler export and public type/ABI projections | Phase 1 | | action construction, graph traversal, scheduling, CAS/cache, environment/sandbox and build failure behavior | Phase 2 | | manifest/lock/work/vendor text parsing, module/source resolution, fetching, source-store policy and source-tree construction | Phase 3 | | native/provider recursion, lowering, link-plan construction, tool adapters and platform policy | Phase 4 | | actual staged bootstrap, fixed-point rebuild and byte comparison | Phase 6 | WW-specific guarantees remain stronger and explicit: frozen artifact builds are deterministic and offline, selections are locked, artifacts are content-addressed, cached objects are rehashed on read, and bootstrap is established by rebuilding and comparing actual bytes. At cutover there is one user-facing build path, as already required by the migration plan. ## 2. Normative vocabulary | Term | Exact meaning | |---|---| | **package** | The WW declarations selected from one directory, compiled together under one declared package name and one package identity. | | **module** | A distributable, versioned source tree rooted by one `ww.mod`, declaring one globally stable module identity and containing zero or more packages. | | **project** | The module or standalone package selected by the user's current command, including its declared products. | | **workspace** | A local, non-published set of module-identity-to-directory overlays described by `ww.work`. It changes location, never identity. | | **dependency** | A typed directed edge: package import, generated-input edge, tool edge, native-provider edge, runtime edge, ordered link edge, source-input edge, or bootstrap-record edge. A source-input edge is content-rooted and has no producer action; it is valid in template/final action inputs but never in `GraphEdgeV1`. A bootstrap-record edge selects the producer action-record or action-result record for `bootstrap.compare`. The edge kind is never implicit. | | **target/platform descriptor** | A canonical architecture/platform/ABI/object/CPU/runtime description. An action labels descriptors by role: execution `B`, product `H`, and optional compiler-output `T`. A target triple is only a short lookup name. | | **artifact** | An immutable byte string or canonical directory tree produced by an action and named by a content digest. Materialized files are copies or links, not the artifact's identity. | | **toolchain** | An immutable descriptor and content closure containing the compiler, action protocol, export/ABI versions, target descriptors, resource files, runtime implementations, and pinned assembler/linker/archive tools. | | **sysroot** | A content-identified target filesystem tree containing the exact headers, libraries, CRT objects, loader metadata, linker scripts, and SDK files exposed to target actions. | | **source identity** | `sha256` of the canonical source-tree encoding in section 4.5. It is independent of download URL and checkout path. | | **version** | An immutable SemVer release label associated with one module identity and one source identity. It is selection metadata, not package identity. | | **product** | A named requested result: executable, static library, shared library, object bundle, test binary, generated tree, documentation tree, or toolchain component. | | **action** | A pure, finite build step with a typed canonical record, declared input artifacts, one execution platform, and declared output paths. | | **build platform (B)** | The platform on which the build actions execute. | | **host platform (H)** | The platform on which the requested product will execute. | | **target platform (T)** | For a compiler-like product, the platform for which that product emits code. It is absent for an ordinary executable or library. | Module and package identities are slash-separated ASCII paths. They are NFC-normalized, case-sensitive, contain no empty, `.` or `..` segment, and do not depend on filesystem case folding. A non-root package identity is written `module-id/package/path`; the root package identity is `module-id`. The selected module catalog records which module owns each package identity. If two selected modules would supply the same package identity, resolution fails rather than choosing a longer prefix. A no-manifest invocation gives its sole root package the reserved internal identity `@standalone/root`; any external test package gets the reserved identity `@test/`. These namespaces cannot be declared by a module or imported from ordinary source. The default standalone executable materializes as `main`, independent of directory basename. A standalone package cannot contain/import another local package or be published until `ww init` gives it a stable module/package identity. ## 3. Source and package rules ### 3.1 One directory, one package A package directory contains its immediate regular source files and source-name symlinks that resolve to regular files. A source-name symlink to a directory is ignored. Nested directories are separate packages. Every selected production source MUST begin with the same canonical `package name;` clause. The declared name MUST be a valid WW identifier. It need not repeat the directory leaf because identity and source qualifier are separate concepts. The following current forms are errors after the migration: - importing a single `.ww` file as if it were a package; - placing multiple package blocks in one compilation unit; - satisfying an unresolved import from an inline package block; - selecting a literal source file as the build root; and - finding packages through ordered `-I` search roots. `ww build ./cmd/tool` selects a directory. A directory with one source file is still the smallest package and needs no extra metadata. ### 3.2 File membership and target selection The current toolchain has one honest target, `linux/amd64`. Production candidates are immediate visible names ending `.ww`, excluding selected `*_test.ww` files. Directory entries beginning `.` or `_` are ignored. Candidate names are byte-sorted before any selected source is opened, parsed, or checked. WW applies Go 1.26.5's filename suffix algorithm to the portion of the basename before its first dot. A final `_test` token is removed for this decision. If the last two remaining underscore-delimited tokens are a known OS followed by a known architecture, both must match `linux/amd64`. Otherwise a final known OS or architecture must match. A known mismatch excludes the file; an unknown or misplaced token leaves it ordinary. The pinned known sets are: ```text OS: aix android darwin dragonfly freebsd hurd illumos ios js linux nacl netbsd openbsd plan9 solaris wasip1 windows zos ARCH: 386 amd64 amd64p32 arm armbe arm64 arm64be loong64 mips mipsle mips64 mips64le mips64p32 mips64p32le ppc ppc64 ppc64le riscv riscv64 s390 s390x sparc sparc64 wasm ``` The suffix requires a nonempty prefix and an underscore. Thus `linux.ww` and `plan9_test.ww` are ordinary files, `x_plan9_test.ww` is excluded, `x_linux_amd64.ww` is selected, and `x_windows_amd64.ww` is excluded. The first dot ends inspection: `x.extra_windows.ww` is ordinary. Pair recognition takes precedence over the final single token; `x_windows_amd64.ww` does not match just because `amd64` does. Conversely `x_amd64_linux.ww` has no OS/architecture pair and matches its final single `linux` token, exactly as Go does. Selection is additive, not replacement-based: every matching file belongs to the package. The production variant then excludes `*_test.ww`; internal and external test classification uses only the already platform-selected test files. After those decisions, distinct selected basenames in one canonical directory MUST NOT be equal under Go 1.26.5's Unicode simple-fold comparison. The check spans the production, internal-test, and external-test selections of one `ww test` product without merging those source units. An ordinary `ww build` sees production names only. Exact basename reuse by another action view of that directory is not a collision. An excluded file creates no source occurrence, collision, import, dependency edge, package/action/variant identity, compiler input, export, archive member, link input, artifact, status, or persistence dependency. Adding or editing one is a producer no-op. Adding, removing, or editing a selected noncolliding file changes the owning unit normally. This applicability is deliberately narrower than Go's `Package.AllFiles`: WW omits wrong-platform and `*_test.ww` names from an ordinary build because those files are not loaded in WW's fixed-target, manifest-free source model. WW implements no source-level build expressions, user tags, target descriptor, `UseAllFiles` escape, `+tag` replacement scheme, or manifest-defined selector. Those would introduce a second build language or a manifest model and are outside the local, manifest-free product. ### 3.3 Imports, names, and resolution The canonical forms are: ```ww import "example.org/codec/hex"; import wire "example.org/protocol/hex"; ``` The quoted string is the package identity. A module package may abbreviate its own module prefix with a relative import written `import "./sub/path";`; resolution replaces `./` with the importing module identity and normalizes the remainder without permitting `..`. Bare dotted imports and filesystem imports are deleted. Standalone packages cannot use relative imports. The default source qualifier is the imported package's declared name. An alias changes only that qualifier. Two imports producing the same qualifier are an error unless one is explicitly aliased. Importing the same identity twice, resolving one identity to two sources, or resolving two selected module records to the same module identity is a loud collision error. Resolution is exact: 1. Build the locked/workspace package catalog by joining every selected module identity with its package directories. 2. Require exactly one catalog owner for the requested package identity; zero is unresolved and two is an identity collision, even when one module prefix is longer. 3. Verify that the catalog directory exists in that module source tree and has the expected package clause. 4. Never search another root and never choose by filesystem accident. Imports are parsed by the compiler front end, not a line scanner. Their union forms package edges, but name visibility remains file-scoped. Every imported qualifier must be used. Package cycles, including self-imports, are reported before compilation with one stable identity path through the cycle. If an import's catalog owner is outside the importing module, that owner MUST be a direct `require` in the importing module's own `ww.mod`; availability through another dependency is not enough. This keeps distribution dependencies as explicit as package imports and prevents accidental reliance on a transitive selection. `ww add` creates the requirement; source is never rewritten. The sole exception is the toolchain's intrinsic standard module, whose identity and source-tree digest are part of the selected toolchain descriptor. It is available without a manifest requirement, including to a standalone package; it is not searched from an installation directory or upgraded independently. ### 3.4 Visibility and internal packages Existing exported-versus-private declaration rules survive. An `internal` directory segment adds one resolution rule: a package under `M/P/internal/Q` may be imported only by the package `M/P` or a package having `M/P/` as a segment prefix. For `M/internal/Q`, the allowed root is module `M` and its descendants. This is checked against the catalog's owning module and package identities, not checkout paths. There are no friend lists or manifest visibility overrides. ### 3.5 Tests, examples, documentation, and generated WW Only `*_test.ww` files are test sources. `package p;` tests compile with package `p`; `package p_test;` tests compile as a separate external package importing the production package normally. Test sources of dependencies are never in a consumer graph. `ww test .` tests one package; `ww test ./...` discovers package directories under the selected module, excluding hidden, underscore-prefixed, vendor, cache, and output directories. Discovery is deterministic and does not follow directory symlinks. Test compilation is cached; each selected test binary is executed on every command and independent binaries may run in parallel. Each test invocation gets only its declared `test-data` mounted read-only under `/data`, its literal `test-env`, a private writable temporary directory, and the selected runner/runtime closure. Project/home/host files and network are denied. Because execution is an observation rather than an artifact action, real clock, process IDs, scheduling, and OS randomness may be exposed and are recorded as runner capabilities; their output is never cached or part of byte reproduction. The same-package test action uses the production package identity with the non-importable action variant `same-test`; it compiles production and test sources together so private names remain visible. An external test uses the reserved `@test/<128-bit-production-identity-digest>` package identity and has a normal direct import of the production package. Neither identity can collide with or be imported by published source. An example is an ordinary package or named product under `examples/`; it has no special dependency semantics. Documentation is derived from source comments and `.wwe` declarations, not by compiling examples during an ordinary build. Generated WW source MUST be declared as an output of an action and as a generated input of exactly one package. It uses the suffix `.wwgen`, does not appear in the source tree, may not contain `import` or `package` clauses, and therefore cannot discover new graph edges after graph construction. It may refer to built-ins and declarations already in its owner package. A generator needing another package must have a checked-in owner file that imports it. This restriction keeps the complete package graph inspectable before executing generators. A generated fragment may contain a foreign declaration only when the owning `package` clause already names its provider slot and the declaration explicitly names that slot. It cannot add a native requirement. After generation, the compiler verifies imports/package clauses are absent and the observed foreign slots exactly match the predeclared set; mismatch is a generator/protocol error. ## 4. Dependency distribution model ### 4.1 When metadata is required A standalone one-directory executable with no non-toolchain dependency builds without metadata. `ww init MODULE` creates a module when the program needs a stable import identity, distribution dependencies, multiple packages/products, generated inputs, or native declarations. A module tree contains exactly one `ww.mod` at its root; nested manifests are an error. A workspace composes separate module roots instead of nesting ownership. `ww.mod` is declarative UTF-8 data. It is not WW code: it has no expressions, variables, imports, include files, macros, loops, user functions, or host conditionals. Strings use JSON escaping; lists preserve source order and record key order is non-semantic. Unknown fields are errors unless a later manifest schema is explicitly selected. A minimal module is: ```text ww-manifest 1 module = "example.org/hello" language = "1" toolchain = { id = "ww.org/toolchain", minimum = "v1.4.0" } require "example.org/codec" { minimum = "v1.2.3" source-index = "https://example.org/codec/.well-known/ww-source" } ``` The complete set of top-level clause kinds in schema 1 is `require`, `product`, `package`, `action`, and `native`. Global scalar keys are only `module`, `language`, and `toolchain`. `require` has required `minimum` and optional credential-free `source-index`; the latter maps origin without changing identity. The schema tables in section 6.9 close all remaining fields. There is deliberately no general `[settings]` escape hatch. The root `main` package is the default executable product, named after the module's last segment, with explicit normalized linkage `dynamic` and runtime `hosted`. Libraries need no product declaration to be imported. Additional or non-default outputs are explicit: ```text product "inspect" { kind = "exe" root = "cmd/inspect" linkage = "dynamic" } ``` ### 4.2 Selection rule Versions are `vMAJOR.MINOR.PATCH` SemVer labels with the usual prerelease order. A requirement is one minimum version, never a range. Selection chooses the greatest minimum requested for each module identity over the complete transitive closure and repeats until stable. This is intentionally the small, monotonic part of Minimal Version Selection, not every behavior of the Go module command. The selected result is written exactly to `ww.lock` by `add`, `update`, or `lock`; build never resolves a newer version. Exactly one version of a module identity is selected. A backward-incompatible major version `N >= 2` MUST declare a module identity ending `/vN`, and imports name that identity. Consequently incompatible releases may coexist as distinct identities without an aliasing version resolver. Two versions of the same identity cannot coexist. There are no feature sets, optional-dependency activation, target-dependent version constraints, upper bounds, wildcard versions, or dependency-wide configuration unification. Target variation belongs in source selection and native-provider declarations after one source closure is selected. The selected source manifests also contribute one minimum for the same toolchain identity. The root lock chooses one exact installed/catalog version at least as high as every minimum and records its descriptor/bundle digests. A different toolchain identity or unsupported language/export/runtime protocol is an error; SemVer alone never overrides protocol compatibility. Dependency manifests do not pin the consumer to their development compiler, while an application remains exactly reproducible from its lock. ### 4.3 Lock file `ww.lock` is generated, canonical, and committed for applications and toolchains. Published libraries SHOULD commit it for their own tests, but consumers resolve from `ww.mod` requirements. A lock record is: ```text ww-lock 1 root-manifest = "sha256:9c..." toolchain "ww.org/toolchain" { version = "v1.4.0" descriptor = "sha256:31..." bundle = "sha256:80..." origin = "https://dist.wwlang.org/toolchain/v1.4.0/" } module "example.org/codec" { version = "v1.2.3" origin = "https://example.org/codec/.ww/v1.2.3.tar.zst" archive = "sha256:4a..." tree = "sha256:f7..." manifest = "sha256:55..." signature = "ed25519:key-id:base64..." provenance = "https://example.org/codec/.ww/v1.2.3.intoto.jsonl" } ``` Records are sorted by identity. Required semantic fields are version, immutable origin, archive digest, canonical source-tree digest, and manifest digest. Signature and provenance are optional records whose verification policy is configured by the user or distributor; hashes are never optional. A signature, when present, covers schema, module identity, version, tree digest, and manifest digest. Lock files never contain local overlay paths or credentials. ### 4.4 Acquisition and network policy `ww add M@V` discovers `M` by the HTTPS convention `https://M/.well-known/ww-source`, unless `--from=URL` or a user-configured longest-prefix source map supplies an index. The index returns immutable archive locations and signed digest records. Redirects and the final URL are recorded. The downloaded module manifest MUST declare exactly `M`; the signed index/lock record, not source text, binds `V` to its tree digest. Private indexes use the same protocol and obtain credentials from the fetch command's credential helper; credentials never enter build actions or lock files. `(module identity, version)` is immutable: observing two signed tree digests for the same pair is an equivocation error recorded in the source store, never an automatic replacement. Yank metadata may prevent new selection but cannot alter or invalidate an already locked digest. Only these operations may initiate network requests: - `ww add`, `ww update`, and `ww lock` while selecting metadata; - `ww fetch --locked` while materializing the already locked source/toolchain closure; - `ww toolchain fetch` for an explicitly named toolchain; and - explicit `ww cache pull` and `ww cache push`; and - explicitly authorized `ww observe` remote execution, which is not a build, test-build, or cached artifact action. The build/analysis phases of `ww build`, `run`, `test`, `doc`, `install`, `graph`, and `explain` deny network access even when an input is absent. They report the missing source digest and the exact `ww fetch --locked` command. They never modify `ww.mod`, `ww.lock`, or `ww.work`. `--frozen` additionally requires those files to be present, canonical, mutually consistent, and unchanged by selection. `--offline` is an explicit assertion of the already mandatory no-network build policy. ### 4.5 Source identity and storage A module source tree contains only directories and regular files; symlinks, devices, sockets, FIFOs, absolute paths, `..`, duplicate normalized paths, and case-fold collisions are rejected. Its identity is: ```text SHA256("ww-source-tree-v1\0" || for each byte-sorted relative path: LP(path) || type || executable-bit || LP(SHA256(file-bytes))) ``` `LP(x)` is an unsigned 64-bit big-endian byte length followed by `x`. Directory entries are included with type `dir`; regular files with type `file`. Ownership, timestamps, archive compression, checkout path, and non-executable permission bits are excluded. Archives are checked both against their blob digest and the unpacked tree digest. The source store is immutable and keyed by tree digest. ### 4.6 Workspaces, vendoring, and distributors `ww.work` is local, declarative, and normally uncommitted: ```text ww-work 1 use "example.org/codec" { path = "../codec" expect = "sha256:f7..." } ``` An overlay replaces only the location for the named module identity. The module at that path must declare the same identity. Its current canonical tree digest is an action input; `expect` makes accidental drift loud but may be updated by `ww work sync`. No import or lock identity changes. `ww vendor` materializes every locked module under `vendor/sha256/` and writes a canonical identity-to-tree `vendor/index.wwv`. Frozen builds may select that source store with `--vendor`; the vendored bytes must match the lock. There is no flattened import tree and no rewritten import statement. An operating-system distributor has three honest options: ship this vendor store, prefill WW's immutable source store, or provide an exact workspace/source map to distro-owned trees. Native system libraries are substituted only through the explicit provider mechanism in section 8.8. A mutable `/usr` lookup is an impure system profile, is local-cache-only, and is rejected by frozen builds. ### 4.7 Closed metadata grammar `ww.mod`, `ww.lock`, `ww.work`, vendor indexes, and toolchain/native descriptors share this lexical grammar; each schema separately closes its allowed headers, clauses, fields, value types, and cardinalities: ```text document = header newline { statement } EOF header = schema-name SP unsigned statement = assignment | clause assignment = key ws "=" ws value ws newline clause = key ws string ws "{" newline { assignment } "}" ws newline value = string | unsigned | boolean | list | record list = "[" ws [ value { ws "," ws value } [ ws "," ] ] ws "]" record = "{" ws [ pair { ws "," ws pair } [ ws "," ] ] ws "}" pair = key ws "=" ws value key = ALPHA { ALPHA | DIGIT | "_" | "-" } string = JSON-string-with-valid-UTF-8 unsigned = "0" | ("1"…"9" { DIGIT }) boolean = "true" | "false" ws = { SP | TAB | newline | comment } comment = "#" { any-character-except-newline } ``` `schema-name` is exactly `ww-manifest`, `ww-lock`, `ww-work`, `ww-vendor`, `ww-toolchain`, `ww-native-map`, `ww-native-sidecar`, `ww-install`, or `ww-bootstrap`. A clause body contains assignments only, so nesting cannot grow into a language. Duplicate keys, duplicate singleton clauses, invalid UTF-8, unknown fields, integer overflow, and a comment marker inside an unclosed string are errors. Whitespace, comments, assignment order, record-key order, and clause order where the schema declares identity keys are non-semantic. List order is semantic. Parsing produces a typed record whose canonical semantic encoding is `WWAR(record)`, not the original text. Its semantic digest is the applicable kind/schema-bound `record_id` from section 6.6. `ww fmt` writes two-space canonical text; generated lock/vendor files MUST already equal that rendering in frozen mode. ## 5. Build model and graph construction ### 5.1 One graph, constructed before execution For every command, `ww` constructs a typed graph in these deterministic phases: 1. Select the project, manifest, lock, workspace, toolchain descriptor, target, and profile. Verify their schemas, canonical identities, and content digests. Missing locked inputs are errors; this phase never fetches. 2. Enumerate selected checked-in package files by section 3.2. Ask the compiler front end to parse package clauses, imports, checked-in foreign declarations, and test metadata. Generated artifacts are known future input slots but do not yet exist. The build driver never scans source lines itself. 3. Resolve every import by identity, reject collisions/internal violations, and compute the complete acyclic package graph. 4. Add statically declared generated-input, host-tool, native-provider, toolchain, runtime, archive, ordered link, and bootstrap-record comparison edges. Match target clauses and reject zero or multiple providers. All generated output names and consumers are known here. 5. Lower nodes to the complete **action-template DAG** and report it. A template names every edge/input slot, tool, policy, and output, but its final key remains unresolved until every predecessor output or selected record content digest is known. Only after this point may a cache be read or a tool execute. 6. As verified cache results or completed predecessors resolve input artifacts, finalize ready action records/keys, query the cache, schedule misses, publish successful artifacts atomically, then materialize requested products. No executed action may add a node, input, output, import, library, flag, or follow-up command. Native C/assembly declarations name complete header/source trees rather than learning dependencies from an ambient compiler depfile. This may conservatively rebuild for an unused header change, but the graph remains complete before execution and the key is correct. `ww graph --actions --format=json` emits the graph after phase 5. Its canonical JSON contains node kind, execution platform, typed input/output slots, incoming edge kinds, target/profile/toolchain digests, and the exact ordered link plan. A resolved node also has its key/cache status; otherwise it has `key: "pending"`, `cache: "unknown"`, and a byte-sorted `waiting-on` list. It contains logical paths only. A collision, cycle, missing provider, undeclared target, or unresolved tool fails graph construction even if a stale cache entry might otherwise satisfy the product. ### 5.2 Built-in action kinds Schema 1 has this closed set of semantic action kinds: - `ww.package`: compile one package to export data, object code, and link metadata; - `ww.init`: synthesize one deterministic retained package-initialization dispatcher from precomputed package link metadata; - `native.compile`: compile one declared C or assembly source unit; - `archive`: construct a static library from an ordered object list; - `link`: construct an executable or shared library from an ordered link plan; - `generate`: execute one declared build-platform tool; - `doc`: render a documentation tree from sources and export data; - `bootstrap.compare`: compare canonical stage outputs and manifests. Adding an action kind changes the action schema. There is no generic rule engine, phony target, implicit suffix rule, command-string target, or shell recipe. An archive is made only for an explicit static-library product or native provider; WW packages are not automatically wrapped in one-member archives. `run` and `test.run` are non-cacheable invocation nodes, not semantic artifact actions. `test.run` consumes the declared data/environment/runner and uses the test sandbox above on every request. `ww run`, after its network-denied build, launches the user's program with the user's runtime authority/environment unless `--sandbox` is explicitly requested; that execution still cannot affect a build cache entry. Both store exit status/logs only as observations. Materialization/install is a third category: a request-local side effect consuming an immutable artifact/install manifest. Neither category can satisfy or poison an artifact-action cache entry. The semantic graph is independent of process boundaries. An implementation MAY run compiler workers in-process or in a bounded pool, but each `ww.package` action still has an independent canonical record and outputs. There is no required background daemon and no daemon state may affect an output. ### 5.3 The finite escape hatch Unusual generation and packaging use a declarative `action`, not a build script: ```text action "protocol-bindings" { tool = "product:tools/schema-gen" platform = "build" inputs = { schema = { file = "protocol/schema.idl" } } outputs = { ww = { file = "generated/protocol.wwgen" } } argv = ["--input", "/in/schema", "--ww", "/out/ww"] env = { LANG = "C", TZ = "UTC" } } package "protocol" { generated = ["action:protocol-bindings:ww"] } ``` The tool is either a named executable in the immutable toolchain or a named WW product built for `H = B`. `/in/NAME` inputs are read-only mounts and `/out/NAME` outputs are initially absent, exclusive writable mounts. The working directory is the empty logical `/work`. Output type is exactly `file` or `tree`; undeclared files fail the action. `argv` is passed directly, never through a shell. Input and output names are identifiers and each path appears through its fixed mount, so there is no template language. The sandbox exposes only the declared tool closure at fixed logical `/tool` paths, `/in`, `/out`, the literal environment map, deterministic locale/time-zone data, and bounded CPU/memory resources. Network, process inspection, host devices, user/home directories, ambient `PATH`, ambient environment, wall clock, writable source, and filesystem paths outside the mounts are denied. Randomness is absent unless a declared seed artifact is mounted. A tool may spawn only executable inputs declared in its tool closure. These isolation rules apply equally to built-in compiler, C, assembler, archiver, linker, documentation, test, and bootstrap executions. Strong enforcement is required for frozen/shared-cache builds; an unsupported host must fail rather than silently weaken isolation. This action can perform arbitrary computation over finite declared inputs, so it is sufficient for code generators, image/file-system builders, binding tools, and signing-input preparation. It cannot inspect the project and invent more work. Dependency modules may declare actions only for outputs consumed by their own packages/products; they cannot register hooks that run merely because the module is present. Every artifact-producing action declares `reproducibility = "required"` in a frozen or official build. Isolation removes undeclared external inputs, but it cannot prove that arbitrary tool internals avoid PIDs, uninitialized memory, ASLR-derived values, or race-dependent output. Such variance is a tool/action defect. Official releases and first shared-cache publication of a custom generator repeat it from clean sandboxes and compare outputs. A node explicitly classified `observation` is never result-cached/shared and may not feed an artifact action; tests and hardware execution use that class. Impure development actions are local-only and outside the byte promise. ### 5.4 Build, host, and target WW uses the conventional three-platform meaning rigorously: ```text B: execution platform on which build actions run H: platform ABI of the produced artifact; executable products are intended to run here T: output platform of a compiler-like artifact that itself is built for H ``` For an ordinary program `T` is absent. The familiar `ww build --target=aarch64-unknown-linux-gnu` spelling sets `H`; it means “build the program that runs on this target.” A compiler product may additionally set `--host=H --target=T`. Any generator used while producing it still executes on `B`; if the generator is itself WW source, its product is compiled with `H = B`. Every action record carries all applicable descriptors, even when two are equal. No rule may infer `H` or `T` from the kernel running `ww`. Cross compilation is therefore the same graph with a different explicit host/target descriptor, not a mode that edits environment variables. In record/JSON field names these are `execution-platform`, `product-platform`, and optional `compiler-output-platform`. Source suffix selection, ordinary native-provider `when`, sysroot, CRT, runtime, and linker selection always match the product platform H. A build-tool dependency instead has its own H equal to the parent action's B. CLI `--target` is only the familiar spelling for selecting the ordinary product platform; it does not rename the GNU roles internally. ### 5.5 Scheduling and failure After graph construction, ready actions run in a deterministic priority order with a user-selected concurrency bound. Priority affects latency only; output bytes and link order come from records, never completion order. Independent actions may finish after another branch fails, but no dependent action starts. On the first observed failure WW stops launching work and cancels its owned in-flight actions. Which failure triggers cancellation is observational and may vary with concurrency; every concurrently observed failure is sorted by stable logical node in the report. `--keep-going` instead continues branches whose dependency closure remains healthy and reports all failures in that stable order. Interrupts cancel only processes owned by this invocation and leave no published partial result. Tool stdout and stderr are captured as artifacts and streamed with node labels. Diagnostics use module-relative logical paths. `--verbose` may display physical mount paths separately, marked non-semantic. A successful action is published only after all declared outputs exist, have valid type/mode, are canonicalized where required, and have been hashed. A failed action is never entered in the action cache. ### 5.6 Atomic publication and materialization CAS files and action-result records are written to same-filesystem unique temporary names, flushed, rehashed, then atomically renamed to their digest locations. For crash durability, WW flushes the parent directory after rename; it publishes and flushes every output before the result mapping. A concurrent publisher of the same digest verifies equality and discards its temporary file. A directory artifact is a canonical tree object whose leaves are CAS blobs. An action-result mapping is published last, so no reader can observe a result before its outputs. Materialization is a request-local side effect outside the action-template DAG. By default requested products appear in `out///`; `--out` and `ww install --prefix` change only where immutable artifacts are copied or copy-on-write reflinked. Hardlinks/symlinks are permitted only when the backing store is enforced immutable against the user and mode changes cannot affect its inode. Executable bits are set by the artifact record, never by a later ambient `chmod`. Replacement uses temporary siblings and atomic rename. `ww clean` removes materialized/project state only; `ww cache gc` is the separate explicit global-cache operation. ### 5.7 Reproducibility contract For official supported targets, WW promises byte-identical artifacts when every artifact action satisfies `reproducibility = "required"` and these are identical: - canonical project source and `ww.lock`; - immutable toolchain descriptor and complete bundle; - target descriptor and build profile; and - all declared action inputs, including generated seeds and signing material. The engine guarantees input isolation, logical paths, and canonical publication; repeat-build certification checks arbitrary tool determinism. The resulting promise is independent of absolute checkout, source-store, cache, output, and temporary paths; wall time, locale, process order, username, UID, and host environment are absent. Logical paths are module/package paths. Debug information uses those logical paths and fixed prefix maps. Archive metadata is canonical; timestamps and ownership are zeroed; deterministic linker build IDs derive from the link key. Official toolchains reject tools that cannot meet this contract. A project source archive plus the complete locked dependency source bytes (a vendor/source-CAS export), its lock, the named immutable toolchain bundle, and every declared external seed/signing input is therefore a complete offline reproduction input. A lock's hashes alone cannot recreate absent bytes. Runtime behavior that depends on a shared library outside the pinned runtime/sysroot closure is not covered, and frozen official profiles prohibit such a dependency. An explicitly selected impure system profile receives no byte-identity promise, cannot publish to a shared cache, and prints every ambient input it accepted. `ww verify reproducible` runs isolated uncached builds under two physical roots and compares every result artifact and action manifest, not just the final executable. ## 6. Action records and cache protocol ### 6.1 Canonical encoding Action records use **WWAR 1**, this deterministic byte encoding: ```text WWAR(record) = 0x57 0x57 0x41 0x52 | u16be(1) | value(record) value(v) = type:u8 | u64be(payload-length) | payload type 0x01 bytes: payload is the bytes type 0x02 string: payload is valid NFC UTF-8 with no NUL type 0x03 uint: payload is minimal unsigned big-endian; zero is one 0x00 type 0x04 bool: payload is exactly 0x00 or 0x01 type 0x05 list: u32be(count) | each (u64be(value-length) | value) type 0x06 map: u32be(count) | each (u64be(key-length) | key-UTF-8 | u64be(value-length) | value) type 0x07 record: u32be(count) | each (u32be(field-tag) | u64be(value-length) | value) ``` Record fields are strictly increasing by numeric tag. Map entries are strictly increasing by raw UTF-8 key bytes. Duplicate/out-of-order keys or tags, leading zeroes in a uint, invalid booleans/UTF-8/NFC, mismatched counts/lengths, unknown schema tags, and trailing bytes are errors. Lists preserve declared order. Schema defaults are always encoded, so no semantic field is inferred from absence. Floats, signed integers, null, and indefinite lengths do not exist. One byte string/string is at most `2^31-1` bytes, a container has at most `2^24-1` members, and nesting depth is at most 64. A content/container-relative logical path string uses `/`, is relative, has no NUL/backslash, empty/`.`/`..` segment, and passes the schema's ASCII-identity or NFC-source-path rule. A field that explicitly permits `.` as its complete root sentinel is the sole exception. These are protocol limits, not host `size_t` limits. Human-readable JSON is a lossless rendering, not the hashed representation. Phase-0 golden vectors include empty/nested records, ordered lists, sorted maps, every rejection, and their complete bytes/digests. The normative empty-record vector is `57574152000107000000000000000400000000`, SHA-256 `138c6acb7f01e91df73cb1d9c3356d18f19d7b8eb8b0a15426bef32e515d0de0`. Each schema assigns every path field a path class. Artifact, source, generated output, install-destination, bundle-relative, sysroot-relative, and vendor-relative paths use the relative rule above. Sandbox-execution paths are path-independent absolute paths only in the closed virtual namespaces `/work`, `/in`, `/out`, `/tool`, and `/data`; schema-1 action working directory is exactly `/work`, and exact sandbox path spellings in argv are encoded. Platform-validated target-runtime paths are a separate type and may be absolute in H's namespace. Workspace locations and observation physical paths are separately typed and never enter an artifact action record or key as host locations. Absolute host paths, filesystem device/inode numbers, mtimes, cache locations, and command process IDs are invalid in action templates and final action records. A physical input enters only through a logical name, content digest, type, and semantic mode. ### 6.2 Required action-record fields Every record contains, in this order: 1. WWAR schema and action kind/version; 2. language edition, compiler protocol, export protocol, object ABI, runtime ABI, manifest schema, and lock schema; 3. B, H, and optional T descriptor digests plus the expanded target fields; 4. toolchain identity, selected descriptor-slice/closure digest, compiler/backend digest, and every executable/shared/resource digest actually used by the action; the distribution bundle root/version authenticates acquisition but unused targets/tools do not invalidate this action; 5. profile fields: optimization, debug, assertions, overflow, panic, sanitizers, LTO, relocation/code model, symbol stripping, and reproducibility policy; 6. logical package/product/action identity and sandbox-virtual working directory (schema 1 exactly `/work`); 7. exact argument vector and a sorted literal environment map; 8. byte-sorted named inputs, each with edge kind, logical path, semantic artifact kind, semantic mode, content digest, and—where applicable—origin package identity; 9. direct export-data inputs byte-sorted by package identity for `ww.package` actions; 10. selected source-membership list and target-selection explanation; 11. typed native declarations: headers, objects, archives, shared libraries, sysroot, SDK, libc, CRT, dynamic loader, linker scripts and their include closures, assembler/linker/archive tools, and ABI-provider slots; 12. the exact ordered link plan, retaining archive groups, whole-archive markers, as-needed state, and repeated libraries; 13. named output paths, types, modes, and canonicalization policies; and 14. sandbox policy/version, resource bounds, and reproducibility classification. Fields irrelevant to an action are encoded as empty values, not inferred. Native flags exist only as typed fields whose meaning is part of a tool adapter. A raw flag can be used only in a custom toolchain declaration and then its exact bytes are part of the record; the official profile has no hidden default flags. ### 6.3 Environment and tool discovery No inherited environment variable is semantic. Built-in actions receive the fixed environment specified by their toolchain adapter. A declarative action receives only its `env` record. `PATH`, compiler-driver defaults, `pkg-config`, shell initialization, host include/library directories, and current directory are never consulted to discover an input. User configuration may choose a cache location, concurrency, output directory, credential helper, source mirror, or display preference; these do not enter an action because they cannot alter output bytes. Choosing a toolchain, target, profile, workspace overlay, native provider, environment value, raw option, or impure system mapping can alter bytes and therefore always enters the record. ### 6.4 Package action inputs and invalidation A `ww.package` action consumes: - the exact selected production or test source files and generated fragments; - their ordered membership metadata; - only the `.wwe` artifacts of direct imported packages; - the compiler/backend and toolchain resources; - B/H/T, target descriptor, profile, language/compiler/export/object/runtime protocols, and manifest/lock schemas; - package-specific predeclared native-provider slots, distinct from selected concrete provider declarations; and - its literal built-in environment and sandbox policy. It emits `.wwe`, one target object, and canonical link metadata. A private change in a dependency changes that dependency's object and the final link key, but not the importer's action key. A public change changes the dependency's `.wwe` and therefore its direct importers. If a rebuilt importer emits byte-identical `.wwe`, the invalidation stops there. Link-only input changes only invalidate link/archive actions; materialization merely recopies a newly selected immutable artifact when its requested result digest changes. A package's own source bytes remain part of its action key even if a compiler could prove a change dead. A target/profile/tool/runtime ABI change creates a different key. There is no timestamp freshness shortcut and no “artifact exists” predicate. ### 6.5 Link action inputs The link action consumes every reachable package/native object digest, explicit archive/shared-library digest, CRT object, runtime object, dynamic-loader choice, linker script closure, sysroot descriptor, target/profile, exact linker tool and resources, and the ordered plan. Objects are ordered by stable package identity; an explicit static product's `members` list controls only that archive's member order. Native archives retain declared order; repeated archives remain repeated; group and whole-archive boundaries are semantic. `-L`/`-l` token collections are not an internal representation. The link result is cacheable. A warm identical build need not invoke the linker. Changing output/materialization path alone does not change the link key. Changing a private package implementation normally preserves importer objects but changes the final link key through that package's object digest. ### 6.6 Complete cache-key formula Let `R` be the complete WWAR record from sections 6.2–6.5. The action key is: ```text K = SHA256("WW-ACTION-KEY\0" || uint64be(len(WWAR(R))) || WWAR(R)) ``` Input entries contain the SHA-256 digest of their canonical artifact bytes/tree, not merely the producer's action key. Thus semantically identical outputs stop rebuild propagation even when their producing source/action key changed. Ordered fields remain ordered; only fields specified as maps are sorted. The domain separator and schemas prevent a digest from one protocol being reinterpreted in another. A successful result record contains `K`, result-schema version, output name/type/mode/digest tuples only. Stdout, stderr, exit/diagnostic presentation, timing, worker identity, resource use, and physical paths go in a separate invocation-observation record. Thus one action key has exactly one semantic successful result even if its logs differ. Observation records may be content-addressed, but never participate in action mapping, cache hits, or reproducibility comparison. CAS identities are type-separated. Blob bytes use their own domain; every structured object is additionally bound to its top-level record kind and schema: ```text blob_id = SHA256("WW-BLOB\0" || u64be(length) || bytes) record_id(kind, schema, record) = SHA256("WW-RECORD\0" || u32be(kind) || u32be(schema) || u64be(length(WWAR(record))) || WWAR(record)) ``` Schema 1 reserves these top-level `kind` numbers: 1 tree, 2 manifest, 3 lock, 4 workspace, 5 vendor index, 6 native map, 7 platform descriptor, 8 toolchain, 9 profile, 10 action template, 11 action record, 12 action result, 13 observation, 14 graph snapshot, 15 native sidecar, 16 native ABI contract, 17 link plan, 18 export, 19 package link metadata, 20 install manifest, 21 bootstrap plan, and 22 selected-tool closure. An unknown kind is never decoded as another record. `TypedDigestV1` is a record with tag 1 domain (`blob` or `record`), tag 2 algorithm (schema 1 only `sha256`), tag 3 record kind (`0` for a blob), tag 4 record schema (`0` for a blob), and tag 5 the exact 32 digest bytes. A field whose type is “typed digest” always means this record; a bare hexadecimal string is only a text rendering. A tree record is schema 1 plus a list sorted by entry-name UTF-8 bytes. An entry is `(name, kind=file|tree, executable:boolean, typed-child-digest)`. `name` is one normalized path segment. Empty directories are explicit tree children; symlinks, hardlink identity, devices, xattrs, uid/gid, mtimes, and non-executable permission bits do not exist. Duplicate normalized or case-fold-colliding names are errors. Validation recursively checks every typed child to a blob; verifying only a root digest is insufficient. ### 6.7 Storage, sharing, and corruption The default cache is per-user, global across that user's checkouts, local, and private to the account: ```text /v1/cas/sha256/aa/bb... /v1/actions/sha256/aa/bb... /v1/quarantine/ ``` The first path stores blob objects and kind/schema-bound structured records; the second maps an action key to `(action-record digest, result-object digest)`. A small ignored project index `.ww/state-v1` references the previous successful graph snapshot, whose logical nodes point to action-record/key/result digests. It roots that history until replacement so explanation can compare records and follow causes; it is disposable and never proves freshness. After explicit GC removes history, `explain` reports `history-unavailable` rather than inventing “stale.” A system-wide cache service requires authenticated isolated writers and the same signed-mapping policy as a remote cache. On every cache read, WW verifies the requested object's digest and canonical type, decodes the mapped action record, recomputes `K` from it, and requires `recomputed K = lookup K = ActionResultV1.tag2` plus `ActionResultV1.tag3 = the mapping's typed action-record digest`. It then verifies all output objects before use or materialization. A mismatch moves only that explicit entry to quarantine, removes its action mapping, reports corruption, and rebuilds. `ww cache verify` walks the store; `ww cache gc` traces retained action results and materializations. A tool upgrade changes its content/descriptor fields and cannot reuse the old key. If two executions of one `reproducibility=required` action key produce different semantic result digests, WW publishes neither as an authoritative replacement, records both observations/artifact sets in quarantine, and fails with a nondeterminism diagnostic. Impure actions have no reusable action mapping. Shared caches are opt-in explicit transports. `ww cache pull` imports only content-addressed objects and action mappings in an Ed25519 signed envelope over `"WW-CACHE-MAP\0"`, cache namespace, action key, action-record digest, result digest/schema, and reproducibility/policy classification. The envelope carries a signing-key ID; configured trust policy handles rotation/revocation. Hashes prove bytes; the trusted cache signing key authorizes the asserted key-to-result mapping. All hashes are reverified. An unsigned/untrusted mapping is treated as a miss even if its referenced blobs exist. `ww cache push` refuses impure, non-reproducible, secret-bearing, or policy-incompatible actions. Literal secret environment values are forbidden; a required secret is a classified file input, redacted from JSON/explain, and makes the action non-shareable. Ordinary build does not contact a shared cache. ### 6.8 Explainability For every node, WW retains its last local record and current record. `ww explain NODE` reports one of `hit`, `not-built`, `missing-result`, `corrupt-result`, `policy-rejected`, or `key-changed`. For `key-changed` it prints the first and, with `--all`, every differing typed field, for example: ```text codec/hex: key changed input direct-export example.org/base: 71… -> a4… caused by base: exported type Header layout changed link hello: key changed package-object example.org/codec/hex: 19… -> 27… ``` `ww explain --path NODE` follows the shortest changed-input path to a source, tool, target, native provider, or policy root. `--format=json` exposes both WWAR renderings and field paths. Export-data differences use the normative `ExportV1` semantic field/type diff; if old content was explicitly GC'd the command reports `history-unavailable`. Cache misses are never explained merely as “stale.” ### 6.9 Version-1 semantic record schemas The following tables freeze schema-1 semantic fields and WWAR numeric tags. `1` means exactly one, `0/1` optional, `*` a list, and `map` unique string keys. Every absent optional value encodes the stated empty/default. Identity-keyed lists are byte-sorted by identity; lists marked `ordered` preserve source/link order. Nested records use the field tags in their named table. Enums reject unknown values rather than passing them to a tool. #### Project and distribution records | Record/tag | Field | Type/cardinality | Rule/default | |---|---|---|---| | `ManifestV1/1` | schema | uint/1 | `1` | | `/2` | module | string/1 | canonical module identity | | `/3` | language | string/1 | language edition | | `/4` | toolchain | `ToolchainRef`/1 | compatible ID and minimum | | `/5` | requires | `Require`/* | sorted by module | | `/6` | products | `Product`/* | sorted by name | | `/7` | packages | `PackageConfig`/* | sorted by relative path | | `/8` | actions | `GenerateDecl`/* | sorted by name | | `/9` | natives | `NativeProvider`/* | sorted by name | | `ToolchainRef/1` | id | string/1 | toolchain identity | | `/2` | minimum | string/1 | minimum compatible SemVer | | `Require/1` | module | string/1 | module identity | | `/2` | minimum | string/1 | SemVer minimum | | `/3` | source-index | string/0/1 | empty means HTTPS convention | | `Product/1` | name | string/1 | unique identifier | | `/2` | kind | enum/1 | `exe`, `static`, `shared`, `object`, `generated` | | `/3` | root | string/0/1 | package-relative path; required except generated | | `/4` | linkage | enum/1 | `dynamic`, `pie`, `static`, `static-pie`, `shared`, `none`; kind-valid | | `/5` | runtime | string/1 | `hosted` default, `minimal`, `none`, or slot | | `/6` | entry | string/0/1 | empty selects typed toolchain default | | `/7` | native | string/* | required slots, sorted | | `/8` | linker-script | `ArtifactRef`/0/1 | empty | | `/9` | providers | `ProviderSelection`/* | sorted by slot | | `/10` | members | string/* ordered | static/archive members; root only by default | | `/11` | action | string/0/1 | required only for generated product | | `/12` | install-name | string/0/1 | platform-validated, empty | | `ProviderSelection/1` | slot | string/1 | ABI slot | | `/2` | use | string/1 | `module#native-clause` | | `PackageConfig/1` | path | string/1 | normalized relative path; `.` root | | `/2` | generated | string/* | sorted `action:NAME:OUTPUT` refs | | `/3` | native | string/* | sorted provider slots | | `/4` | test-data | `InputDecl`/* | sorted names, read-only under `/data` | | `/5` | test-env | map | literal non-secret test environment | `ArtifactRefV1` is permitted in declarative configuration records (including toolchain/native records) and action templates, but never in a final action record. Its tags are: 1 `ArtifactNamespace` (`source`, `generated`, `package`, `toolchain`, `sysroot`, `provider-output`, `cas`, or `graph`); 2 owner identity (empty only for a root source); 3 normalized logical name/path; 4 semantic artifact kind (`file`, `tree`, `object`, `archive`, `shared`, `import-library`, `script`, `crt`, `loader`, `native-sidecar`, `native-abi`, `export`, `package-link`, `action-record`, or `action-result`); 5 optional expected `TypedDigestV1`; and 6 mode (`data` or `executable`). A local source may omit tag 5 because analysis hashes it. A `cas`, external prebuilt, toolchain, or sysroot reference must include it. A generated/package/provider output gets its digest only from the declared predecessor output. Absolute host paths are invalid. `InputSlotRefV1`, `TemplateInputV1`, `ResolvedInputV1`, built-in/template/final action-output records, and `ResultOutputV1` use that same closed semantic artifact-kind enum; `GenerateDecl.OutputDecl` remains restricted to `file` or `tree`. In schema 1, `file`, `object`, `archive`, `shared`, `import-library`, `script`, `crt`, and `loader` require a blob digest. `tree` requires record kind 1, `native-sidecar` kind 15, `native-abi` kind 16, `export` kind 18, and `package-link` kind 19, each at record schema 1. Schema-1 artifact-kind values 14 `action-record` and 15 `action-result` require record kinds 11 and 12, respectively, at record schema 1. They are input-only and valid only for `bootstrap.compare`; they are invalid in built-in, template, or final action outputs and in `ResultOutputV1`. Any other digest domain, record kind, or schema is invalid kind substitution. The `graph` namespace has one exact form. Its consumer is `bootstrap.compare`, the `TemplateInputV1` edge kind is `bootstrap-record`, and `ArtifactRefV1.tag2` is the producer logical node. Tag 3 is the Identifier selector `action_record` for artifact kind `action-record` or `action_result` for artifact kind `action-result`; tag 5 is absent. `ArtifactRefV1.tag6` and `TemplateInputV1.tag5` are `data`, `TemplateInputV1.tag4` repeats the corresponding artifact kind, and `TemplateInputV1.tag6` is empty. No other consumer, edge kind, selector, kind, expected digest, or mode is valid for this namespace. These inputs and edges are bijective: each `graph` template input has exactly one `bootstrap-record` `GraphEdgeV1`, and each such edge has exactly one `graph` template input. The edge's consumer node is the enclosing template node, its consumer input slot equals `TemplateInputV1.tag1`, its producer node equals `ArtifactRefV1.tag2`, and its selector equals `ArtifactRefV1.tag3`. `InputSlotRefV1` has tag 1 slot name and tag 2 expected semantic artifact type. A final action record contains no `ArtifactRefV1`: every artifact-bearing field is recursively lowered to an `InputSlotRefV1`. `TemplateInputV1` tags are 1 unique slot name, 2 edge kind, 3 `ArtifactRefV1`, 4 expected semantic type, 5 semantic mode, and 6 optional origin package identity. `ResolvedInputV1` tags are 1 the same slot name, 2 edge kind, 3 normalized logical name/path, 4 semantic artifact type, 5 semantic mode, 6 the resolved `TypedDigestV1`, and 7 optional originating package identity. It contains no producer node, producer action key, action- template digest, physical output path, or unresolved filesystem lookup. Thus all content that a native plan, link plan, source-selection record, or tool closure can read is also present exactly once in action-record tag 10 under a named slot. `GenerateDecl` fields are fixed as follows: tag 1 name; 2 tool artifact/product reference; 3 platform enum (schema 1 only `build`); 4 `TargetConstraint` or empty; 5 input map of `InputDecl`; 6 output map of `OutputDecl`; 7 ordered string argv; 8 literal string environment map; 9 `ResourcePolicy`; 10 reproducibility enum `required` or `impure`. `InputDecl` is tag 1 kind (`file`, `tree`, `artifact`, `tool`), 2 logical reference, 3 optional expected typed digest, 4 semantic mode. `OutputDecl` is tag 1 kind (`file`, `tree`), 2 logical output path, 3 executable boolean. `ResourcePolicy` is tags 1 max CPU count, 2 memory bytes, 3 output bytes, 4 process count; zero selects the toolchain's recorded bound, never “unlimited.” | Record/tag | Field | Type/cardinality | Rule/default | |---|---|---|---| | `LockV1/1` | schema | uint/1 | `1` | | `/2` | root-manifest | typed digest/1 | semantic manifest record | | `/3` | toolchain | `ToolchainLock`/1 | exact closure | | `/4` | modules | `ModuleLock`/* | sorted identity | | `/5` | native-map | `LockedObject`/0/1 | empty | | `ToolchainLock/1…5` | id, version, descriptor, bundle, origin | strings/digests | all required | | `ModuleLock/1` | module | string/1 | identity | | `/2` | version | string/1 | selected SemVer | | `/3` | origin | string/1 | exact final archive URL | | `/4` | archive | blob digest/1 | required | | `/5` | tree | tree digest/1 | required | | `/6` | manifest | record digest/1 | required | | `/7` | signature | bytes/0/1 | empty | | `/8` | provenance | string/0/1 | empty | | `LockedObject/1…3` | origin, digest, signature | string/digest/bytes | origin+digest required | `WorkV1` is tag 1 schema, tag 2 sorted `Use` records, tag 3 sorted local provider overrides. `Use` tags are module, path, expected source-tree digest. A provider override has slot, provider ID, product-platform constraint, contract digest, artifact-tree digest, and provenance in tags 1–6. `VendorV1` is tag 1 schema, tag 2 lock-record digest, tag 3 sorted entries `(module, version, source-tree digest, vendor-relative path)` in tags 1–4. `NativeMapV1` is tag 1 schema, tag 2 exact product-platform descriptor digest, tag 3 sorted provider overrides, and tag 4 signer/provenance record. #### Profiles, templates, actions, results, and trees A profile is toolchain data, not an open project map: | Tag | `ProfileV1` field | Values | |---|---|---| | 1 | name | identity | | 2 | optimization | `0`, `1`, `2`, `3`, `size` | | 3 | debug | `none`, `line`, `full` | | 4 | assertions | boolean | | 5 | overflow | `trap`, `wrap` | | 6 | panic | `abort`, `runtime` | | 7 | sanitizers | sorted toolchain capability IDs | | 8 | LTO | `none`, `thin`, `full` | | 9 | relocation | effective `static`, `pic`, `pie` | | 10 | code-model | exact target capability ID | | 11 | TLS default | exact target capability ID | | 12 | strip | `none`, `debug`, `all` | | 13 | reproducibility | `required`, `impure` | | Tag | `ActionTemplateV1` field | Rule | |---|---|---| | 1 | schema | `1` | | 2 | kind/version | exact built-in kind or generate version | | 3 | protocol record | language/compiler/export/object/runtime/manifest/lock; compiler protocol is distinct from compiler/backend byte identity | | 4 | platform roles | B, H, optional T descriptor refs | | 5 | selected tool closure | identity plus semantic closure digest/resources | | 6 | profile | complete `ProfileV1` | | 7 | logical identity/cwd | normalized identity; cwd exactly `/work`, path-independent | | 8 | argv | ordered strings | | 9 | environment | sorted literal map, no secrets | | 10 | input slots | sorted `(name, edge kind, producer/output or source ref, type, mode)` | | 11 | source selection | ordered selected membership plus reasons | | 12 | native/link template | closed predeclared provider slots, concrete providers, and ordered link records | | 13 | outputs | sorted name/path/type/mode/canonicalization | | 14 | sandbox/reproducibility | exact policy/version/bounds/class | `ActionRecordV1` has the same top-level tags, but tag 10 contains sorted `ResolvedInputV1` records and every `ArtifactRefV1` elsewhere in the template is replaced by the corresponding `InputSlotRefV1`. The tag-12 native/link value is therefore a resolved plan; it cannot contain an unresolved artifact reference, producer, physical path, or readable artifact locator/digest outside tag 10. ABI/layout/contract digests embedded in a referenced sidecar or contract are semantic verification values, not authority to read another object. No producer action key substitutes for a content digest. The tag-12 native/link record separately encodes the sorted predeclared provider slots, concrete selected-provider declarations, and the optional ordered link policy or resolved plan. A `ww.package` action contains exactly its `PackageConfigV1` native-slot list and empty concrete-provider and link-policy/ plan values; finalization copies that slot list unchanged. Concrete provider selection does not enter a package action merely because the provider satisfies one of those slots. Finalization interns every source, direct export, package/native object, archive, shared library, header/sysroot tree, generated output, tool/resource, CRT, loader, script, and init dispatcher into exactly one named template input. For `bootstrap.compare`, it also interns every selected raw action record and action result as a separate named input. Finalization erases the `graph` namespace, producer node, and unresolved selector form. The corresponding tag-10 `ResolvedInputV1` retains edge kind `bootstrap-record`, logical selector `action_record` or `action_result`, matching artifact kind, `data` mode, and the resolved typed digest; that digest is the sole authority to read the raw record. Predecessor output and selected-record digests resolve those slots lazily. The producer logical node, producer output path, producer key, and template digest are graph/provenance facts only and do not enter the consumer's `ActionRecordV1` or `K`. Two producers that deliver the same typed bytes to the same semantic slot therefore produce the same downstream record and key. `ActionResultV1` tags are: 1 schema, 2 the 32-byte action key, 3 typed action-record digest, and 4 sorted `ResultOutputV1` records. `ResultOutputV1` tags are 1 unique output name, 2 semantic artifact type, 3 mode (`data` or `executable`), and 4 `TypedDigestV1`. `ObservationV1` separately uses tags 1 schema, 2 logical invocation, 3 optional action key, 4 exit status/signal, 5 stdout blob, 6 stderr blob, 7 timing/resources, and 8 physical runner metadata; it is never an action result. `TreeV1` tags are 1 schema and 2 ordered entries. `TreeEntryV1` tags are 1 name, 2 kind (`file`, `tree`), 3 executable boolean (false for tree), and 4 typed child digest. `GraphSnapshotV1` tags are 1 schema, 2 logical root, 3 sorted `GraphNodeV1` records, and 4 sorted `GraphEdgeV1` records. `GraphNodeV1` tags are 1 logical node ID, 2 typed action-template digest, 3 optional 32-byte action key, 4 optional typed action-record digest, and 5 optional typed action-result digest. `GraphEdgeV1` tags are 1 consumer node ID, 2 consumer input slot, 3 producer node ID, 4 producer output name, and 5 edge kind; edges sort by that five-field tuple. Tag 4 is an ordinary producer output name except that a `bootstrap-record` edge uses selector `action_record` or `action_result`. That branch resolves the actual producer `GraphNodeV1.tag4` or tag 5, respectively; it never selects an `ActionOutputV1` or `ResultOutputV1`. If the selected producer tag is absent, the input remains unresolved and blocks finalization. The `source-input` kind is invalid in `GraphEdgeV1`. Non-action source inputs live only in the consumer template rather than invented graph nodes. The project index contains only its typed graph-snapshot digest. #### Target, toolchain, native, interface, and handoff records | Tag | `PlatformDescriptorV1` field | Rule | |---|---|---| | 1 | schema | `1` | | 2 | name | canonical lookup name | | 3 | arch/vendor/os/environment/object format | five exact enums | | 4 | endian/address spaces/pointers | complete integer-width map | | 5 | integer/data-layout | widths, alignments, aggregate algorithm | | 6 | C ABI/data model | exact IDs and calling-convention table | | 7 | float/variadic/name decoration | exact ABI records | | 8 | CPU baseline/features/atomics | baseline plus required/forbidden sets | | 9 | minimum OS/SDK | typed version record | | 10 | TLS/unwind capabilities | sets plus defaults | | 11 | relocation/code capabilities | supported sets plus defaults | | 12 | executable/shared/page rules | typed object-format rules | | 13 | hosted policy | hosted/freestanding plus capability set | | 14 | object/runtime ABI protocols | exact IDs | `TargetConstraintV1` tags 1–17 are, respectively: optional exact descriptor digest; arch; vendor; OS; environment; object format; hosted; C ABI; data model; float ABI; CPU baseline; required feature set; forbidden feature set; minimum SDK; relocation; code model; PIC requirement. Empty scalar/set means no constraint. Matching is exactly section 8.4; no expression field exists. `ToolchainV1` tags are: 1 schema; 2 ID; 3 version; 4 the same complete protocol record used by action tag 3; 5 sorted `Tool` records; 6 sorted platform descriptors; 7 sorted profiles; 8 sorted link policies; 9 runtime/provider records; 10 bundle tree digest/signature provenance. A `Tool` is `(name, bundle-relative path, executable blob digest, ordered dynamic tool dependencies, resource-tree digests, adapter record)` tags 1–6. A link policy is `LinkPolicyV1`: tag 1 product-platform descriptor; 2 product kind; 3 linkage; 4 profile constraint; 5 runtime selector (`hosted`, `minimal`, `none`, or an exact provider slot); 6 one ordered link-policy token template; and 7 output ABI/install policy. Policies sort by the five-field selection key and a zero/multiple match is an error. CRTs and scripts are `ArtifactRefV1` tokens, not basenames. A dynamic loader is one restricted `dynamic-loader` token holding both its artifact and runtime interpreter path; PE/COFF platform-image policy is an ordered provider token rather than a fabricated loader artifact. `SelectedToolClosureV1` deterministically projects only the relevant tools/resources/platform/profile/policy into tags 1–7; that projection—not unrelated bundle members—is action-key input. #### Native artifact and ABI subrecords Compact manifest paths are lowered to `ArtifactRefV1` before WWAR encoding and then to action input-slot references before execution. The native records are: | Tag | `IncludeTreeRefV1` field | Rule | |---|---|---| | 1 | tree | `ArtifactRefV1` of kind `tree` | | 2 | class | `quote`, `user`, `system`, or `framework` | | 3 | subdirectory | normalized tree-relative path; `.` default | The provider's include list is ordered because header search order is semantic. The same tree may occur more than once with another class or subdirectory. | Tag | `NativeSourceV1` field | Rule | |---|---|---| | 1 | name | unique provider-local identity | | 2 | source | `ArtifactRefV1` of kind `file` | | 3 | language | exact toolchain capability ID, such as `c11` or `gnu-assembly` | | 4 | preprocessing | `none` or `c-preprocessor` | | 5 | include-indices | ordered indexes into the provider include list; empty means all | | 6 | defines | sorted literal macro map; duplicates with provider defines error | Target, profile, relocation/PIC/code/TLS policy, tool, and dialect adapter come from the enclosing `native.compile` record. Raw source flags do not exist. | Tag | `PrebuiltObjectV1` field | Rule | |---|---|---| | 1 | name | unique provider-local identity | | 2 | object | `ArtifactRefV1` of kind `object` | | 3 | sidecar | `ArtifactRefV1` of kind `native-sidecar` | | 4 | contract | `ArtifactRefV1` of kind `native-abi` | | Tag | `ArchiveV1` field | Rule | |---|---|---| | 1 | name | unique provider-local identity | | 2 | archive | `ArtifactRefV1` of kind `archive` | | 3 | sidecar | archive-level `ArtifactRefV1` of kind `native-sidecar` | | 4 | members | ordered `ArchiveMemberV1` list in physical order | | 5 | contract | `ArtifactRefV1` of kind `native-abi` | `ArchiveMemberV1` tags are 1 member name, 2 member blob `TypedDigestV1`, and 3 object-sidecar `ArtifactRefV1`. Duplicate names are legal only at distinct positions; member order is never sorted. The referenced archive sidecar records the ordered member-sidecar record digests as well as the physical member facts. | Tag | `SharedImportLibraryV1` field | Rule | |---|---|---| | 1 | name | unique provider-local identity | | 2 | kind | `elf-shared`, `macho-dylib`, or `pe-import` | | 3 | link-artifact | shared object/dylib/import-library `ArtifactRefV1` | | 4 | link-sidecar | `ArtifactRefV1` of kind `native-sidecar` for tag 3 | | 5 | runtime-identity | exact SONAME, install-name, or DLL name | | 6 | runtime-artifact | exact deployable shared object/dylib/DLL `ArtifactRefV1` | | 7 | runtime-sidecar | `ArtifactRefV1` of kind `native-sidecar` for tag 6 | | 8 | contract | `ArtifactRefV1` of kind `native-abi` | | 9 | runtime-requires | sorted `NativeRuntimeRequirementV1` list | ELF and Mach-O tags 3 and 6 may resolve to the same bytes. For PE, tag 3 is the import library and tag 6 its matching DLL. A platform image still supplies tag 6 as a content-identified artifact within that image. `NativeProviderV1` tags are therefore: 1 name; 2 provided slot; 3 `TargetConstraintV1`; 4 ordered `IncludeTreeRefV1`; 5 ordered `NativeSourceV1`; 6 sorted provider define map; 7 ordered `PrebuiltObjectV1`; 8 ordered `ArchiveV1`; 9 ordered `SharedImportLibraryV1`; 10 sorted required slots; 11 ordered link-token templates; and 12 an `ArtifactRefV1` of kind `native-abi`. Every ABI contract and sidecar is an independently encoded, content-addressed record. In a resolved action, those records and every artifact field above are `InputSlotRefV1` values; source/action/provider output digests live only in action tag 10. A sidecar's internal artifact digest must equal the corresponding object/archive/shared input-slot digest, and its contract digest must equal the kind-16 `TypedDigestV1` of the referenced native-ABI input record. Section/layout/provenance digests inside a sidecar are verification facts, not locators from which the action may read undeclared content. | Tag | `NativeABIContractV1` field | Rule | |---|---|---| | 1 | schema | `1` | | 2 | slot | exact ABI-provider slot | | 3 | platform | `NativeABIPlatformV1` | | 4 | symbols | sorted `NativeSymbolContractV1` list | | 5 | types | sorted `NativeTypeContractV1` list | | 6 | runtime-requires | sorted `NativeRuntimeRequirementV1` list | | 7 | features | `NativeFeatureContractV1` | | 8 | minimum-platform | optional `PlatformVersionV1` | | 9 | code | `NativeCodeContractV1` | Its typed record identity is `record_id(16, 1, contract)` as defined in section 6.6. Every schema-1 digest identifying a complete `NativeABIContractV1` is the corresponding record-domain, kind-16, schema-1 `TypedDigestV1`. WW computes it; a supplied digest is never accepted in place of the record. Subordinate layout, calling-convention, type-contract, and header-contract digests remain their separately specified semantic values. | Tag | `NativeABIPlatformV1` field | Rule | |---|---|---| | 1 | object-format | exact format capability ID | | 2 | object-class | exact class/word-size ID | | 3 | endian | `little` or `big` | | 4 | machine-ABI | exact architecture object ABI ID | | 5 | C-ABI | exact C ABI ID | | 6 | data-model | exact data-model ID | | 7 | data-layout | canonical layout digest | | 8 | calling-conventions | canonical convention-table digest | | 9 | float-ABI | exact ID | | 10 | variadic-ABI | exact ID | | 11 | symbol-ABI | exact decoration/versioning ABI ID | | 12 | object-ABI | exact object protocol ID | | 13 | runtime-ABI | required WW runtime ABI ID or empty | `NativeSymbolContractV1` tags are: 1 exact external name; 2 exact version or empty; 3 kind (`function`, `data`, `tls`, `ifunc`); 4 role (`define`, `require`); 5 binding (`strong`, `weak`); 6 visibility (`default`, `protected`, `hidden`); 7 calling-convention ID or empty; 8 canonical function/object type-contract digest; and 9 optional byte size. Symbols sort by `(name,version,kind,role)`; duplicate keys error. `NativeTypeContractV1` tags are: 1 stable binding/header-qualified identity; 2 kind (`opaque`, `scalar`, `enum`, `struct`, `union`, `function`); 3 exposure (`opaque`, `layout`); 4 canonical target-specific layout/signature digest; 5 optional size; 6 optional alignment; and 7 optional canonical header/macro contract digest. Types sort by identity and duplicates error. `NativeRuntimeRequirementV1` tags are 1 provider slot, 2 required ABI-contract digest, 3 phase (`link`, `load`, `both`), and 4 optional SONAME/install-name/DLL identity. They sort by `(slot,phase,runtime-identity)`; conflicting requirements for one slot error. `NativeFeatureContractV1` tags are 1 CPU baseline or empty, 2 sorted required feature IDs, 3 sorted forbidden feature IDs, and 4 sorted atomic-capability IDs; required and forbidden sets must be disjoint. `PlatformVersionV1` tags are 1 version-family ID and unsigned 2 major, 3 minor, 4 patch, 5 revision. Versions compare lexicographically over tags 2–5 only after tag 1 equality. `NativeCodeContractV1` tags are 1 PIC (`any`, `required`, `forbidden`); 2 sorted TLS-model IDs; 3 unwind ABI ID or `none`; 4 sorted personality/runtime symbols; and 5 sorted required/forbidden relocation records, each record being tag 1 capability ID and tag 2 requirement (`required` or `forbidden`). `NativeSidecarV1` is evidence, not a second contract. Its tags are: 1 schema; 2 artifact `TypedDigestV1`; 3 evidenced `NativeABIPlatformV1`; 4 sorted evidenced `SectionFactV1`; 5 sorted evidenced `SymbolFactV1`; 6 sorted evidenced `RelocationFactV1`; 7 evidenced sorted architecture attribute/notes map; 8 evidenced `NativeMachineFactsV1`; 9 native ABI-contract digest; 10 sorted `NativeRuntimeRequirementV1`; and 11 `ProvenanceV1`. An evidenced value is `EvidenceV1`: tag 1 enum (`inspected` or `declared`) and tag 2 the value whose type is fixed by the containing field. `NativeMachineFactsV1` tags are 1 `NativeFeatureContractV1` and 2 `NativeCodeContractV1`. `SectionFactV1` tags are 1 name, 2 format type, 3 flag set, 4 size, 5 alignment, 6 optional content digest. `SymbolFactV1` tags are the nine `NativeSymbolContractV1` fields plus tag 10 section and tag 11 value/offset. `RelocationFactV1` tags are 1 section, 2 offset, 3 exact relocation ID, 4 symbol, 5 signed addend encoded as `(negative:boolean,magnitude:uint)`, and 6 target section. `ProvenanceV1` tags are 1 producer/tool typed digest, 2 source/build record typed digest, 3 attestation bytes, and 4 signer/policy ID. A frozen opaque input requires accepted attestation for every `declared` value. `LinkTokenTemplateV1` and final `LinkTokenV1` share tags: 1 kind; 2 artifact; 3 provider slot; 4 string value; 5 enabled boolean; 6 validated path; 7 runtime path; and 8 ordered nested tokens. Tag 2 is `ArtifactRefV1` in a template and `InputSlotRefV1` in a final action. Valid nonempty combinations are exactly: object/archive/shared/linker-script/version-script/export-map/def-file use tag 2; the template-only provider kind uses tag 3; group/whole use tag 8; as-needed uses tags 5 and 8; runtime-search uses tags 4 and 6; install-name, entry, and retain use tag 4; and dynamic-loader uses tags 2 and 7. Every other field encodes its empty/default value. A final `LinkTokenV1` forbids `provider`; provider selection and its ordered fragment are recursively expanded at that exact position before the plan is final. Section 8.6 constrains valid nesting. A toolchain `LinkPolicyV1` template additionally permits `splice` (tag 4 is exactly `product-objects`, `init-dispatch`, `native-providers`, or `product-controls`) and `script-slot` (tag 2 is an optional policy-default script). Those two kinds are forbidden in project/native link declarations and in a final plan. The selected policy template is flattened in list order. Each splice kind occurs exactly once and expands to its already computed ordered product list; the single required `script-slot` becomes one `linker-script` at the same list position using the product's explicit script when present, otherwise the policy default, and disappears only when both are empty. A product script therefore replaces, never combines with, the default. Ordinary policy tokens—including CRT objects, compiler runtime, dynamic loader, and system-provider slots—stay exactly where declared. System providers are ordered template tokens, not a sorted set. Each expands to its selected provider's concrete token fragment; dependencies expand recursively, and a provider cycle is an analysis error. Every expanded artifact, sidecar, and ABI contract is a tag-10 input. A provider such as a PE platform image that adds no linker token instead contributes its resolved contract slot to the plan's non-link policy field. After expansion no provider or splice partition remains. `LinkPlanV1` tags are 1 schema; 2 the exact product-platform/kind/linkage/ profile/runtime-policy selection record; 3 the single fully expanded ordered `LinkTokenV1` stream; 4 selected linker/tool/resource slot refs; 5 selected non-link platform/runtime/provider ABI-contract and sidecar slot refs; and 6 output ABI/install policy. Every file-bearing token and verification record references action tag 10. Only this resolved flattened plan enters the link action key. `ExportV1` (the WWAR body after `.wwe` magic) tags are: 1 schema; 2 reader capabilities; 3 language/type protocol; 4 product-platform/C/object/runtime ABI; 5 package identity/name; 6 sorted exported-surface origin/type contract table; 7 canonical type graph; 8 sorted exported declarations/constants/foreign symbols; 9 public initialization/ABI facts; 10 public-type digest; 11 public-ABI digest. Section 7.2 defines excluded non-semantic fields. `PackageLinkV1` (`.wwlm`) tags are 1 schema, 2 package identity, 3 platform/object/runtime ABI, 4 package-object digest, 5 defined/required foreign symbols, 6 predeclared provider slots/contracts, 7 init symbol/dependency facts, 8 install/link requirements. Tag 6 contains exactly one compiler-derived `ProviderContractV1` for each package action tag-12 predeclared slot, and its sorted slot projection must equal that predeclared list. It cannot add a provider slot or graph edge. `InstallManifestV1` tags are 1 schema, 2 product identity/key, 3 sorted entries `(artifact digest, mode, relative destination)`, 4 runtime-resolution policy, 5 sorted shared/runtime closure, 6 target/toolchain/ABI provenance. Absolute prefix is deliberately absent. `BootstrapPlanV1` tags are 1 schema, 2 bootstrap-host contract, 3 ordered source refs/digests, 4 portable-C compiler/output settings, 5 recorded host-C command/tool closure, 6 stage-1 outputs, 7 production toolchain closure, 8 identical logical stage-2/3/4 action roots, 9 semantic fixed-point output roles, and 10 raw-record fixed-point roles. No clause or executable step exists beyond that closed plan. These sections fix the architectural fields, but they do not make Phase 0 an executable specification of every reference or key transformation. Phase 0 transcribes only their wire-visible record fields, tags, enum values, union discriminants, encoded defaults, field order, record kinds, wrapper framing, and digest preimage formulas into the checked-in compact schemas. Cross-field validity, construction, resolution, projection, lowering, and failure behavior belong to the executable phase that implements them. The Phase 0 generator and golden vectors determine bytes, not future build-engine semantics. No phase may silently add a wire field, renumber an assignment, change an encoded default, or alter a frozen digest formula. ## 7. Interface and artifact protocol ### 7.1 Package outputs Every `ww.package` action, including a root package, emits the same three named artifacts: ```text export.wwe deterministic binary export data package.o one target object link.wwlm deterministic package link metadata ``` These are names inside an immutable action result, not globally meaningful filenames. The cache is keyed by digests and logical package identity, so there is no `__root` special case and no dotted import path used as an artifact basename. A root object and dependency object obey identical protocols. `link.wwlm` declares the package object's target, object ABI, defined/required foreign symbols, required native-provider slots, initialization ordering, and runtime ABI. It attests facts/edges already present in the action-template DAG; it may not introduce a provider, dependency, or action after compilation, and a mismatch is a compiler/build-protocol error. It does not contain raw linker flags. Ordinary package objects are fed directly to the product link. An archive exists only when an explicit static-library product asks the `archive` action to combine its ordered declared `members` (default: root package only). Transitive package/native dependencies remain typed link requirements in the library's install manifest and are not silently copied into multiple archives. A deliberately self-contained archive must list every member explicitly and pass duplicate-symbol/provider checks. Language initialization never depends on linker input order. `ww.init` consumes all reachable `.wwlm` artifacts, topologically orders initialization by package imports with byte-sorted ties, diagnoses duplicate/cyclic init facts, and emits one dispatcher object. The link plan explicitly roots that dispatcher and every referenced init symbol against section garbage collection. ### 7.2 WW Export Data 1 (`.wwe`) `.wwe` is a cache/build protocol, not source text and not a long-term binary distribution promise. It starts with the eight-byte magic `WWEX\0\0\0\1` and a WWAR-encoded body. The magic is fixed framing that is reconstructed and verified around the body; it does not create a second blob identity. The typed `.wwe` identity is `record_id(18, 1, ExportV1)` over that body. The body contains: 1. export schema, language edition, type-system protocol, and required reader capabilities; 2. target descriptor, C ABI, object ABI, and runtime ABI digests; 3. full package identity and declared package name; 4. a sorted table of originating package/type identities and declaration-level public ABI digests actually referenced by the exported surface; 5. a canonical type graph sufficient for type checking, layout, calling convention, and code generation of every exported declaration; 6. exported constants, variables, functions, methods, types, and explicit foreign symbols; and 7. the public initialization/ABI facts needed by an importer. Declarations are sorted by `(kind, exported name, stable overload discriminator)`; type-graph nodes are assigned by deterministic structural traversal. Integer and floating constants use canonical target-independent bit encodings until a target conversion is part of their type. Function parameter **names**, source locations, comments, unused imports, private function bodies, and declaration order are not semantic and are omitted. Documentation/source mapping is a separate optional artifact and cannot invalidate an importer. Unmanaged layout sometimes depends on facts that are private at the source level. An exported representation therefore records size, alignment, field/base offsets, calling convention, niche/tag rules, and relevant private padding or opaque-field descriptors without exposing private names. `@repr("c")` types also record the exact C data model and layout algorithm version. Opaque types record only the operations and layout promises permitted to clients. ### 7.3 Direct imports with deep public closure An importer opens one `.wwe` for each direct import and no transitive interface file. If a direct dependency's API mentions a type originating in a deeper package, its `.wwe` embeds a canonical deep descriptor for the portion of that type required to understand and lay out the direct API. The descriptor retains the originating package/type identity and digest of that exact referenced contract—not the originating package's entire public ABI. It does not pretend the type belongs to the middle package. This rule gives both correctness and bounded reads: ```text source/package imports -> direct .wwe inputs direct .wwe -> complete meaning of that direct API link graph -> all reachable package objects ``` A public change in a leaf rebuilds direct reverse dependencies. Propagation continues only while each rebuilt package's `.wwe` bytes change. A private leaf change never enters an importer key. This replaces source-like transitive interface prepending and its quadratic composed units. This bounds interface **opens and reparsing**, not necessarily total descriptor bytes: heavily re-exported type graphs can duplicate deep descriptors. Phase 1 measures total `.wwe` size and structural duplication on the real library graph. Only if that is material may a later export-schema revision intern immutable per-declaration descriptors; direct-import semantics do not change. ### 7.4 Public and ABI digests The `.wwe` content digest identifies its complete target-specific bytes. It also contains two domain-separated hashes: - **public type digest** over names, types, constants, visibility, and language semantics; and - **public ABI digest** over target layouts, calling conventions, exported symbol contracts, runtime ABI, and representation facts. Compile actions normally depend on the whole `.wwe` content digest. Tools such as documentation may depend only on the public type digest when their action kind explicitly permits it. Link compatibility checks use the ABI digest. Digest subsetting is protocol-defined; callers cannot choose arbitrary ignored fields. ### 7.5 Symbols and identity Internal WW symbols are mangled from a protocol-versioned hash of the full package identity plus declaration identity, never from a leaf name or artifact filename. Resolver rules ensure only one source/version supplies that package identity. An explicitly foreign symbol is exactly the source-declared spelling and participates in duplicate-provider checks. Package version and distribution origin are absent from mangling because they are not identity. An incompatible major version has a different `/vN` module identity and therefore different WW symbols. Native C symbols do not gain this protection; their provider slots and link collision rules must reject incompatible co-selection. ### 7.6 Compatibility and deterministic serialization A consumer accepts only the exact export/type/object/runtime protocol combination declared compatible by its immutable toolchain descriptor. A new optional record still requires a new export schema and reader capability. Unknown records are not silently dropped. Target descriptor and ABI mismatches are errors before a compiler or linker runs. Because `.wwe` is rebuilt from locked source, WW does not need an indefinitely stable compiler-internal export format. A toolchain upgrade changes action keys and may rebuild the graph. Public native-library ABI stability is a separate, explicit provider contract. Release/bootstrap byte comparisons include `.wwe`, objects, link metadata, action records, and executables. ## 8. Native integration and cross compilation ### 8.1 Complete target descriptors A target triple is a user-facing alias. Before graph construction it expands to an immutable target descriptor containing at least: - architecture, vendor, operating system, environment, and object format; - endianness, pointer widths/address spaces, integer/long widths, alignment and aggregate-layout rules; - C ABI/data model, calling conventions, name decoration, variadic convention, TLS ABI capabilities/default, floating ABI, and unwind model; - baseline CPU, required/forbidden CPU features, minimum OS/SDK version, and atomic capability; - supported/default relocation and code models, executable/shared-library rules, and page constraints; - hosted versus freestanding policy; and - compatible object ABI and runtime ABI protocol identifiers. The triple `x86_64-unknown-linux-gnu` is insufficient by itself to identify CPU features, sysroot, glibc, loader, or linker. Those are separate descriptor/input digests. `--cpu` and `--feature` produce a new canonical expanded descriptor; the host CPU is never probed to select target features unless the user explicitly requests the impure alias `native`, which is rejected by frozen/shared builds. The descriptor supplies ABI invariants plus supported/default policy values. A profile/product selects the effective relocation, code, PIC/PIE, and TLS policy from those permitted sets; the normalized effective values appear once in the action record. A conflicting or unsupported selection is rejected, never resolved by precedence between duplicate fields. This follows the native facts exposed by LLVM data layouts and Clang's cross compilation/toolchain documentation, while making their often-driver-selected inputs explicit ([LLVM data layout](https://llvm.org/docs/LangRef.html#data-layout), [Clang cross compilation](https://clang.llvm.org/docs/CrossCompilation.html), [Clang toolchain](https://clang.llvm.org/docs/Toolchain.html)). ### 8.2 Toolchain closure (`toolchain.wwt`) An immutable toolchain bundle has a canonical `toolchain.wwt` descriptor with: ```text ww-toolchain 1 id = "ww.org/toolchain" version = "v1.4.0" protocols = { language = "1", compiler = "1", export = "1", object = "1", runtime = "1", manifest = 1, lock = 1 } tool "wwc" { path = "bin/wwc", digest = "sha256:..." } tool "cc" { path = "bin/clang", digest = "sha256:..." } tool "as" { path = "bin/llvm-mc", digest = "sha256:..." } tool "ld" { path = "bin/ld.lld", digest = "sha256:..." } tool "archive" { path = "bin/llvm-ar", digest = "sha256:..." } target "aarch64-unknown-linux-gnu" { descriptor = "targets/aarch64-linux-gnu.wwt" sysroot = { tree = "sha256:...", path = "sysroots/aarch64-linux-gnu" } runtime = "runtime:aarch64-linux-gnu@1" libc = "c:glibc@2.39" link-policies = [ { kind = "exe", linkage = "dynamic", profile = ["debug", "release"], runtime = "hosted", tokens = [ { kind = "object", artifact = "sysroot:lib/crt1.o" }, { kind = "object", artifact = "sysroot:lib/crti.o" }, { kind = "splice", value = "product-objects" }, { kind = "splice", value = "init-dispatch" }, { kind = "splice", value = "native-providers" }, { kind = "splice", value = "product-controls" }, { kind = "provider", slot = "c:compiler-rt@1" }, { kind = "provider", slot = "c:glibc@2.39" }, { kind = "dynamic-loader", artifact = "sysroot:lib/ld-linux-aarch64.so.1", runtime-path = "/lib/ld-linux-aarch64.so.1" }, { kind = "script-slot", artifact = "toolchain:lib/ldscripts/elf.lds" }, { kind = "object", artifact = "sysroot:lib/crtn.o" } ] } ] } ``` Every path is bundle-relative and every executable, shared tool dependency, resource directory, built-in header tree, target descriptor, runtime, sysroot, CRT, default script, and adapter is covered by the bundle's canonical tree digest. The engine invokes exact paths and passes explicit target/sysroot/resource arguments. A tool's compiled-in search outside the sandbox cannot resolve. The compact `sysroot:`/`toolchain:` references in the example normalize to full `ArtifactRefV1` records containing the individual typed digest obtained from that authenticated tree; the shorthand itself never enters WWAR. The whole bundle digest authenticates acquisition. An action key uses the transitive selected descriptor slice/tool/resource/sysroot/runtime closure only; adding an unused target or unrelated tool to a republished bundle does not cause global recompilation. Changing any selected byte/protocol still changes the key. Official bundles may use LLVM, GNU binutils, or another implementation per target; the architecture does not expose that choice as project semantics. Tool adapters translate WW's typed record to exact argv and declare all injected inputs. A custom bundle must do the same and pass conformance/reproducibility tests before frozen mode accepts it. WW permanently owns the language compiler, export/object/runtime ABI protocols, target descriptor schema, action engine, and official bundle definitions. It does **not** permanently own the assembler, linker, archiver, C compiler, or SDK. The current `w6a`/`w6l` may serve as migration inputs, then are removed once a pinned external closure passes parity. This is the smaller long-term system. ### 8.3 C ABI and foreign declarations Foreign declarations are explicit source contracts: ```ww @abi("c") @symbol("write") @provider("c:libc") fn c_write(fd s32, data *u8, count usize) ssize; @repr("c") type Header struct { tag u32; length u16; }; ``` The compiler checks that every type has a defined representation for the selected C ABI and records symbol, calling convention, variadic status, layout, and explicitly named provider slot in `.wwe`/`.wwlm`. `@provider` is mandatory for each foreign declaration (a group annotation may supply it lexically), and the owning package metadata must require that slot; WW never infers it from a symbol spelling or link position. A foreign declaration with no provider, two definitions of a strong symbol, incompatible calling conventions, or mismatched layout digest is a pre-link diagnostic where possible and a mandatory link failure otherwise. C headers are not searched or parsed implicitly. Bindings are either checked-in WW source produced by an explicit `ww bindgen c` command, or a declared `generate` action whose inputs include the exact header trees, target descriptor, preprocessor, macro map, include roots, and binding tool. The generated result records the declared whole input-tree digests, observed include trace as non-semantic audit metadata, and C ABI digest. The trace cannot add an input; a future finer-grained scan would require a new built-in action still keyed by the complete allowed include-tree digest. No build invokes ambient `pkg-config`; `ww native snapshot-pkg-config` is an explicit, impure acquisition command that converts one selected host configuration into a reviewable native provider record and content snapshot. ### 8.4 Native declarations Schema 1 uses two connected declarations. A package lists the ABI slots it requires: ```text package "compress/zlib" { native = ["c:zlib@1"] generated = ["action:zlib-bindings:ww"] } ``` A provider declares exact target artifacts and dependencies: ```text native "zlib-linux-aarch64" { provides = "c:zlib@1" when = { os = "linux", arch = "aarch64", environment = "gnu", c-abi = "aapcs64", float-abi = "hard", requires-features = ["neon"], minimum-sdk = "linux:5.10.0.0" } include-trees = [ { tree = "native/zlib/include", class = "user", subdirectory = "." } ] sources = [ { name = "adler32", source = "native/zlib/adler32.c", language = "c11", preprocessing = "c-preprocessor", include-indices = [0], defines = {} } ] defines = { ZLIB_CONST = "1" } objects = [] archives = [] shared = [] requires = ["c:libc"] link = [ { kind = "object", artifact = { namespace = "provider-output", owner = "zlib-linux-aarch64", name = "adler32", kind = "object", mode = "data" } } ] abi = { file = "native/zlib.wwabi" } } ``` Allowed provider fields are exactly `provides`, `when`, `include-trees`, `sources`, `defines`, `objects`, `archives`, `shared`, `requires`, `link`, and `abi`. `when` is a finite conjunction. It may contain exact `descriptor-digest`, `arch`, `vendor`, `os`, `environment`, `object-format`, `hosted`, `c-abi`, `data-model`, `float-abi`, `cpu-baseline`, `relocation`, `code-model`, and `pic`; `requires-features`/`forbids-features` use subset/ disjoint-set matching; `minimum-sdk` matches only a product platform whose declared minimum is at least that value. It has no general expression. All matching candidates are retained: identical provider/artifact digests coalesce, while multiple different matches require the product's explicit provider map rather than a specificity guess. The textual `abi = { file = PATH }` form parses `PATH` as one complete canonical `NativeABIContractV1` subdocument, encodes it as top-level record kind 16, and lowers the provider field to an `ArtifactRefV1` containing that typed record digest; an inline complete record is equivalent. The local source blob and parsed contract are both hashed. The file form is not a digest assertion or a build-time include, and partial contracts are invalid. `sources` entries support only toolchain-declared C language editions and assembly dialects. Each source has an exact file digest and sees only the listed include trees/defines and toolchain headers. `objects`, `archives`, and `shared` name content-identified prebuilt artifacts plus their target/object/ABI records. A local `path` is content-hashed during analysis; a literal expected digest is needed only for an external/prebuilt record. A provider may mix source and prebuilt inputs, but every produced object is its own `native.compile` action. There is no filesystem library search. `abi` is not an opaque user assertion. It is the recomputed digest of a canonical native ABI contract containing slot, product-platform ABI/data model, calling conventions, symbol names/versions/kinds, referenced C layout/header-contract digests, required runtime slots, CPU/features, minimum SDK, and PIC/TLS/unwind requirements. Foreign bindings carry the expected contract or compatible declaration-level subset. WW cross-checks the contract against compiled objects, shared/import-library sidecars, and declared providers before link. ### 8.5 Assembly and object files Assembly source declares an official external-tool dialect (`gnu`, `llvm-integrated`, or another exact toolchain capability), preprocessing mode, target, and CPU feature contract. The current `w6a` Plan-9-style dialect is a migration input and is not accepted after cutover. The selected assembler executable and resources are action inputs. A source for one target cannot be selected for another by extension alone. Prebuilt objects carry a sidecar native record with content digest, object format, architecture, ABI, required CPU features, defined/undefined symbols, PIC/TLS/unwind properties, and producer provenance. WW verifies the object format/class/endian/machine header, sections, symbol table, relocations, notes, and architecture attributes against every mechanically inferable sidecar fact; the same inspection recurses into archive members and shared/import libraries. Source-level C contract, libc/runtime compatibility, and provenance are not fully inferable from object bytes, so frozen opaque prebuilts additionally need a signature/attestation accepted by policy. A missing or contradictory record is an error, not permission to ask the host linker what happens. ### 8.6 Static/shared libraries and ordered linking Native `link` is an ordered list of typed template tokens: ```text { kind = "object", artifact = "object:NAME" } { kind = "archive", artifact = "archive:NAME" } { kind = "shared", artifact = "shared:NAME" } { kind = "provider", slot = "c:zlib@1" } { kind = "group", items = [...] } { kind = "whole", items = [...] } { kind = "as-needed", enabled = true, items = [...] } { kind = "linker-script", artifact = "file:NAME" } { kind = "version-script", artifact = "file:NAME" } { kind = "export-map", artifact = "file:NAME" } { kind = "def-file", artifact = "file:NAME" } { kind = "runtime-search", policy = "origin-relative", path = "lib" } { kind = "install-name", value = "@rpath/libname.so" } { kind = "dynamic-loader", artifact = "file:LOADER", runtime-path = "/lib/ld.so" } { kind = "entry", symbol = "_start" } { kind = "retain", symbol = "ww_init_abcd" } ``` Those are the complete schema-1 project/native template kinds. `provider` is recursively replaced at its exact position by the chosen provider fragment; the final kinds are every listed kind except `provider`. The toolchain-only `splice` and `script-slot` kinds also lower away as specified in section 6.9. Every file-bearing final token resolves to a declared typed artifact and digest. Nested `items` contain only link tokens; repetition is represented by repeating a list entry and is never deduplicated. `group` contains archives or provider templates that resolve only to archives, `whole` contains archives only, and `as-needed` contains shared inputs or provider templates that resolve only to shared inputs; any other expansion or nesting is invalid. Runtime-search/install-name values are validated by the selected platform adapter; frozen bundled policy permits only relocatable origin-relative paths. Entry/retain tokens become the pinned linker's typed entry/undefined-root mechanism. Raw flags exist only inside a content-identified custom toolchain adapter. The plan is not a set and is never alphabetically reordered. The selected toolchain policy template determines global position: it can place start CRT before the product-object splice and end CRT after runtime providers, rather than relying on one universal ordering rule. Inside `product-objects`, WW objects use stable package-identity order. Inside `native-providers`, fragments use requester-before-provider topological order, which gives `libA` before the `libB` it requires. `product-controls` carries the declared entry/retain/install tokens; `init-dispatch` carries its single retained object when needed. Cyclic static archives must be represented by one explicit `group`; an undeclared provider cycle is an error. Repetition, whole-archive, as-needed, export maps, and symbol-version scripts remain exact records in the flattened canonical plan. An archive action preserves declared member order and canonicalizes header timestamps, ownership, modes, and string tables. A shared-library input includes its link-time artifact, SONAME/install-name, ABI digest, transitive runtime requirements, and deployable runtime artifact digest. Merely finding the same basename in a host directory is never equivalence. The installation manifest also fixes runtime resolution. ELF bundled policy copies the exact shared closure under a digest-namespaced relative `lib/` and uses an origin-relative RUNPATH; Mach-O uses exact `@rpath`/install names; Windows places named DLL artifacts in the declared application directory beside their matching import libraries. A platform-image provider may instead bind an exact loader/system tree. An OS-managed mutable shared library is an impure runtime policy: link bytes can still be recorded, but WW does not promise that execution will load a particular digest. Linker scripts are declared content inputs. The adapter resolves/audits only file-bearing directives such as `INCLUDE`, `INPUT`, `GROUP`, and `SEARCH_DIR` for the pinned linker dialect; included files and permitted sysroot trees are in the record. The pinned linker—not WW—interprets section placement, expressions, symbols, memory regions, and target semantics inside the closed sandbox. Unresolved `SEARCH_DIR`, absolute host paths, and implicit default scripts are errors. GNU `ld` documents that scripts and archive order change link semantics; WW therefore preserves rather than abstracts them away ([GNU ld scripts](https://sourceware.org/binutils/docs/ld/Scripts.html), [GNU linker](https://sourceware.org/binutils/docs/ld.html)). ### 8.7 libc, CRT, SDK, loader, and freestanding products A hosted platform entry names one exact sysroot/SDK and the available libc, system, compiler-runtime, and WW-runtime providers; it does not name one universal CRT sequence or loader. The selected toolchain link policy for `(product-platform descriptor, product kind, linkage, profile, runtime selector)` supplies the exact ordered token template containing CRTs, compiler runtime, system-provider slots, script slot, and any platform-appropriate loader contract. Compiler and linker drivers run through no-defaults adapters and receive only that declared closure, so they cannot fall back to B's `/usr`. A product chooses a runtime policy: ```text product "kernel" { kind = "exe" root = "kernel" linkage = "static" runtime = "none" entry = "_start" native = ["freestanding:boot@1"] linker-script = "native/kernel.ld" } ``` For an executable, `linkage` is exactly `dynamic`, `pie`, `static`, or `static-pie`; shared-library products use `shared`. The toolchain maps `(product kind, linkage, profile, product-platform, runtime selector)` to one exact ordered policy template; selection never ignores `runtime`. Loader presence follows the platform's executable rules. On an ABI with an explicit program interpreter, `dynamic` and `pie` executables must name its runtime path and exact provider artifact; `static` and `static-pie` must not. A shared library has a runtime identity and dependencies but no executable program interpreter. PE/COFF-style platforms without a separate interpreter bind the exact platform-image/loader contract through system-provider policy rather than inventing a pathname. Different product policies therefore cannot accidentally share one CRT/loader sequence. `runtime` is `hosted`, `minimal`, `none`, or a named provider. `none` supplies no libc, CRT, loader, or WW runtime; compiler helper routines must be supplied by a declared provider or rejected. `minimal` names an exact freestanding runtime. Entry symbol, memory/linker script, relocation/code model, panic/stack policy, and any boot image action are explicit. Kernel-style targets never inherit the hosted target's defaults. Schema 1 permits `none` only for object/static products and `static` or `static-pie` executables. Its selected link template must contain no CRT, dynamic-loader, libc, compiler-runtime, or WW-runtime token. `minimal` and named providers declare their valid product/linkage set as capabilities; `hosted` uses the platform's hosted set. A product/linkage/runtime tuple outside that set is rejected during graph construction. The policy's single `script-slot` uses the product's `linker-script` when present, replacing the default at the same ordered position. The target/toolchain declares the runtime capability required by every compiler-emitted helper and language operation. During graph construction a `none`/`minimal` product is rejected if selected source operations require an unavailable allocation, panic, stack, arithmetic, TLS, unwind, or other runtime capability; this is not deferred to an unexplained undefined linker symbol. ### 8.8 Provider conflicts and system substitution One link namespace may select exactly one provider digest for an ABI slot such as `c:zlib@1`, `c:libc`, or `runtime:ww@1`. Multiple requirements for the same slot coalesce only if they resolve to the same provider and ABI digest. Different providers, ABI major slots that export colliding unversioned symbols, and two native modules claiming the same strong symbols are loud identity-collision errors. WW never chooses whichever library appears first. When more than one contract-compatible provider matches, the root product must select one explicitly: ```text product "hello" { kind = "exe" root = "." linkage = "dynamic" providers = [ { slot = "c:zlib@1", use = "example.org/zlib#zlib-linux-aarch64" } ] } ``` The provider ID is `(declaring module identity, native-clause name)`, rendered with `#` only in metadata. Selection cannot change a dependency's required ABI contract; the chosen provider must satisfy every declaration-level contract. Two incompatible native versions can coexist only if they use distinct provider slots **and** their symbols/runtime names are namespaced or versioned so the link record proves no collision. Otherwise the build must adapt one behind a wrapper, use dynamic isolation, or fail. Language-level multiple-version selection cannot solve a C global-symbol collision. A distro system provider is a normal provider record mapping exact logical artifacts to content digests and ABI metadata. If those files live under `/usr`, the mapping snapshots/re-hashes them before graph construction and changes the key whenever they change. It is marked impure unless the directory tree itself is immutable and content-identified. Raw `-L`, `-l`, `LD_LIBRARY_PATH`, compiler defaults, and build-time `pkg-config` are not accepted substitutes. A portable distributor substitution uses a closed `ww-native-map 1` file: ```text ww-native-map 1 target = "sha256:product-platform-descriptor..." provider "c:zlib@1" { use = "distro.example/native#zlib" contract = "sha256:..." artifact-tree = "sha256:..." provenance = "https://distro.example/provenance/zlib.jsonl" } ``` `ww lock --native-map=FILE` records the map digest/origin in `ww.lock`; frozen mode accepts only that exact signed/content-verified map. `ww.work` may contain the same `provider` clause for local development, but it is an impure overlay and frozen mode rejects it. This gives OS packagers an offline substitution mechanism without changing imports or silently consulting `/usr`. ### 8.9 Cross-compilation behavior All code-generating tools execute on B. WW/C/assembly compilation for the requested ordinary product emits H objects using only H's target descriptor, sysroot, headers, runtime, and native providers. A compiler-like product built for H may later emit T code, but no T program executes during its own build. Object headers and sidecars are checked before linking, so a host object cannot silently enter a target product. `ww test --target=H` always builds target test binaries. It executes them only when `H = B` or the toolchain declares an explicit content-identified runner (local emulator or simulator plus immutable image) as an invocation tool. Otherwise it reports “built, not run” unless `--require-run` was requested, in which case it fails. The runner and its platform image are action inputs; no ambient emulator is discovered. Remote hardware/device testing is a separate explicit `ww observe test --runner=NAME` operation with declared endpoint/capability authority. It may use network/devices but is a non-build observation: remote state is reported, it never populates artifact/shared caches, and it is outside byte-reproducibility claims. Ordinary `ww test` retains the no-network policy. This model supports new targets without running a compiler on them: an existing host toolchain adds a target descriptor, backend, object adapter, sysroot/runtime, and native providers, then builds and tests through a declared runner or hardware step. GNU's build/host/target distinction is useful vocabulary, but WW records the complete descriptors rather than only triplets ([Autoconf triplets](https://www.gnu.org/software/autoconf/manual/autoconf-2.71/html_node/Specifying-Target-Triplets.html)). ## 9. Command-line design ### 9.1 The ordinary path The default workflow is deliberately short: ```sh ww init example.org/hello ww build ww run -- argument ww test . ``` `ww init MODULE` creates `ww.mod`, a root `main.ww` only when the directory is empty, and a lock selecting the currently invoked immutable toolchain. It does not add a dependency. In an existing one-directory `main` package, `ww build` works without `init`; the invoking toolchain and standalone source identity are shown in verbose output. `ww build [DIR|PRODUCT]` builds the default root product or one named product. The default profile is the fully specified `debug` profile; `--profile=release` selects the toolchain's immutable release profile. `ww run` first performs that same build, then runs only a product with `H = B`; arguments after `--` are never interpreted by the build. There is no command that means “build and opportunistically download whatever is missing.” If a locked source or toolchain is absent, the diagnostic names its digest and asks for `ww fetch --locked`. ### 9.2 Tests, examples, docs, and installation ```sh # Exactly one package. ww test ./internal/codec # Every package below the current module root. ww test ./... # Compile cross-target tests and require a declared runner. ww test ./... --target=aarch64-unknown-linux-gnu --require-run # Build an ordinary example product and render documentation. ww build example:examples/packet ww doc ./... --out=out/doc # Materialize a named release product under a prefix. ww install inspect --profile=release --prefix=/opt/ww ``` Test package discovery and result reporting remain deterministic under `-j N`. Compilation is cached, but every selected test binary runs. An installation manifest lists every copied artifact, digest, mode, runtime dependency, and relative destination and is materialized as `.wwinstall`. Installation never discovers libraries in the prefix and never mutates the cache artifact. ### 9.3 Inspecting the graph and cache ```sh ww graph --packages ww graph --actions ww graph --actions --format=json > graph.json ww explain example.org/hello/internal/codec ww explain --path --all product:hello ww cache verify ww verify reproducible --profile=release ``` `graph` performs analysis but no build action. A node whose producer output does not yet exist has a known action shape and incoming edges but a `pending` key; its final key is computed when predecessor content digests become available. `explain` compares available current records with the project index and likewise does not build. These commands never fetch. ### 9.4 Adding, fetching, updating, freezing, and vendoring ```sh # Query the module's conventional source index, add a minimum, and lock closure. ww add example.org/codec@v1.2.3 # The same operation with an explicit private or non-conventional origin. ww add corp.example/codec@v1.2.3 --from=https://packages.corp/codec/ # Materialize exactly the existing lock without changing any project file. ww fetch --locked # Change one direct minimum and recompute the complete lock atomically. ww update example.org/codec@v1.4.0 # Recompute after an intentional manifest edit. ww lock # Materialize the exact locked source closure in the project. ww vendor --locked # A frozen, offline build from already present locked inputs. ww build --frozen --offline --vendor ``` `add` and `update` write `ww.mod` and `ww.lock` together through temporary files only after the entire selection and integrity check succeeds. `lock` writes only `ww.lock`. `fetch` and `vendor` never change selection. Without `--vendor`, WW uses the immutable source store; with it, every vendor digest is reverified. `add --from=URL` records that credential-free index as the requirement's `source-index`; archive redirects/final origin remain exact lock metadata. An ordinary non-frozen build still never updates an inconsistent lock: it fails with the exact `ww lock` command. Frozen mode additionally rejects workspaces, impure providers, noncanonical metadata, unlocked tools, and any source digest not named by the lock. `--offline` is useful in automation as an assertion but does not weaken or strengthen the normal build network denial. ### 9.5 Cross compilation and toolchain selection ```sh # Select a product host platform (the familiar cross-build form). ww build --target=aarch64-unknown-linux-gnu --profile=release # Select exact CPU semantics rather than probing the build machine. ww build --target=x86_64-unknown-linux-gnu \ --cpu=x86-64-v3 --feature=-avx512f # Build a compiler that runs on H and emits code for T. ww build compiler:wwc \ --host=aarch64-unknown-linux-gnu \ --target=riscv64-unknown-none-elf # Acquire and lock an exact toolchain before building; only fetch uses network. ww toolchain fetch ww.org/toolchain@v1.4.0 ww lock --toolchain=ww.org/toolchain@v1.4.0 ww build --toolchain=ww.org/toolchain@v1.4.0 ``` The selected command toolchain must match the common ID, satisfy every minimum, and equal the root lock's exact descriptor. A digest selection is exact; an ID/version selection resolves only through the lock or installed signed catalog and never during build. `ww toolchain list --targets` shows descriptors and sysroot/runtime digests, not just triples. `ww lock --toolchain` changes only the lock's exact toolchain selection when the chosen version satisfies every manifest minimum; it does not rewrite those minimums. ### 9.6 Deliberately absent commands/options There is no `ww build --fetch`, build-time package-manager hook, raw `-L`/`-l`, global import search path, arbitrary compiler/linker environment injection, manifest evaluator, or command that installs dependencies into a mutable global source namespace. Expert escape hatches are explicit toolchains, native provider records, and finite declarative actions; all remain visible in the graph/key. ## 10. Toolchain and bootstrap design ### 10.1 The durable stage-zero seed The smallest credible recovery seed is: ```text bootstrap/ww0.c generated portable C99 snapshot bootstrap/bootstrap.plan canonical source/tool/output plan bootstrap/SHA256SUMS expected seed and plan digests ``` `ww0.c` is generated at release time from the same compiler sources as the production compiler, with a deliberately non-optimizing portable C backend and the minimal support routines concatenated into one translation unit. It is not a second hand-maintained compiler and is never used in ordinary production builds. The resulting `ww0` retains that portable C-emission path: it contains only enough compiler, export writer, C output, and fixed-plan execution to emit stage-1 C from the enumerated source closure and have the named host C closure compile it. It has no resolver, network client, general manifest engine, cache, test coordinator, or installation framework. The release process regenerates `ww0.c` and fails if its bytes differ from the checked-in snapshot. Keeping portable source rather than four opaque host binaries permits recovery on a new architecture with a C99 implementation. The cost of the simple C emitter is accepted because it bounds and exposes the seed; it is a release backend, not another production path. The bootstrap-host contract is narrower than “any C99”: hosted C99 with `CHAR_BIT == 8`, exact `uint8_t/uint32_t/uint64_t`, two's-complement signed integers, binary file I/O, at least 32-bit address space and the published source/ object size limits. The snapshot uses no host floating-point result or undefined signed overflow. Compile-time assertions plus a tiny I/O/integer conformance probe run before compilation. Supported implementation modes and required headers are enumerated in `bootstrap.plan`; an implementation outside the contract is not silently called portable. ### 10.2 Stage transitions and fixed point Recovery uses these exact stages: 1. A named host C implementation compiles `ww0.c` to `ww0`. Its executable, version output, command, headers, libc, assembler, and linker are recorded in `bootstrap-host.wwar`; they are part of the trusted base, not silently blessed. 2. `ww0 bootstrap/bootstrap.plan` runs on B, emits portable C for the locked production compiler/driver, and uses that same recorded host C closure to produce **stage 1 with H = B**. Stage 1 must run locally; distributable cross compilers are built only after the local fixed point. 3. Stage 1 uses the pinned production target/tool closure to perform a normal frozen build of the same sources for `H = B`, producing **stage 2**. 4. Stage 2 repeats the identical logical build to produce **stage 3**. 5. Stage 3 repeats it to produce **stage 4**. 6. `bootstrap.compare` first requires stage-2 and stage-3 **semantic output sets**—compiler/driver executables, export/object/runtime artifacts, and the installed semantic bundle tree—to be byte-identical. Producer action records and provenance are excluded because stage 2 was built by stage 1 while stage 3 was built by stage 2. Once those compiler bytes converge, it requires stage-3 and stage-4 semantic outputs **and raw action/result records** to be byte-identical; their producer compiler digests are then equal. Each raw record is a separately named `action-record` or `action-result` input in action tag 10; comparison metadata or a digest outside tag 10 is not read authority. Stage 1 need not equal stage 2: portable-C and production backends may generate different code. Stage 2 MUST equal stage 3 semantically, and stage 3 MUST equal stage 4 completely. A canonical stage semantic manifest lists only role/output artifact digests, never its producer. A mismatch reports the first differing output or action field and is a release failure. Two absolute roots and two concurrency levels are used for the official fixed-point job. This fixed point proves self-consistency and path/order reproducibility; it does not by itself defeat Ken Thompson's trusting-trust attack. Official releases also perform **diverse seed compilation** with two independently sourced host C toolchains where available, publish both bootstrap-host records, regenerate the C snapshot from the converged WW source/compiler, and compare converged semantic outputs before signing. This is additional evidence, not a claim of formal diverse-double-compilation proof. ### 10.3 Trusted-computing-base accounting The bootstrap report lists, by content digest: - `ww0.c`, `bootstrap.plan`, and their tiny C support layer; - host C compiler/preprocessor, headers, libc, assembler, linker, loader, and OS kernel used to create/run `ww0`; - bootstrap assembler/linker/archive tools and their shared/resource closure; - source/lock/toolchain descriptor trees; and - the SHA-256 and signature verification implementations/keys. That is the reproducible software/input closure. The operational trusted computing base additionally includes CPU, firmware, memory/storage behavior, kernel, and execution environment; the report names the available hardware/ firmware attestations but does not pretend a source hash removes physical trust. Nothing is called “trusted” merely because it was found on `PATH`. A recovery build with unpinned system tools may establish a new local fixed point but cannot claim byte identity with an official release. An official reconstruction uses a published content-identified host/bootstrap closure and compares its advertised digests. ### 10.4 Toolchain distribution and selection Each release publishes source plus locked-source-closure archive, `ww0.c`, lock file, platform toolchain bundles, `toolchain.wwt`, stage-2/3/4 semantic and action/result manifests, fixed-point report, digests, signatures, and provenance. Binary bundles are conveniences verified against the descriptor, not irreplaceable seeds. A user either selects the project-locked toolchain or an exact command-line digest; WW never downloads a new compiler while building. Runtime ABI, export protocol, object ABI, and action-schema compatibility are declared independently. A compiler refuses a runtime whose ABI it does not support. Toolchain upgrades can retain source compatibility while intentionally invalidating all relevant action keys. ### 10.5 New-architecture and no-compiler recovery For a new H satisfying the bootstrap-host contract, compile `ww0.c`; `ww0` emits the modified production compiler as portable C and the H C compiler builds the locally runnable stage 1. Add/pin H's production object/assembler/linker closure, then reach the stage-2/3/4 fixed point. Alternatively an existing B toolchain may cross-build that H compiler, but it executes only through an explicit runner. For a new T only, no target-local compiler is required: add the backend/target descriptor, object tests, sysroot or freestanding runtime, and linker provider to an existing B/H toolchain. When no suitable WW compiler exists, the checked-in C seed is sufficient. When no C compiler exists either, a platform must provide one previously built `ww0` binary plus its exact source/digest, or bootstrap a C implementation; WW does not claim a smaller physical trusted base than the machine can execute. ## 11. Current-system assessment This section records the verified baseline at commit `ca2cadeb4173e8190cd4c8bcc25e7da25bcdb0bc`. Line references describe that commit and are implementation evidence, not requirements for the replacement. ### 11.1 Current invariants - POSIX Make selects ambient `CC`, `AR`, optional `ccache`, and flags; builds the Cstage tools; then uses the Cstage driver to build WWstage tools into separate work directories. Make repeats manually enumerated transitive source prerequisites for each self-hosted target ([Makefile](../Makefile), lines 7–20 and 105–279). - `ww build` creates fixed-array package nodes keyed by dotted import spelling, discovers imports with a hand-written scanner separate from the compiler parser, rejects directory-package cycles, visits dependencies in DFS postorder, and invokes packages serially. The graph is capped at 256 packages ([C driver](../cmd/ww/main.c), lines 333–370 and 670–700). - An imported directory is a separately compiled package. An imported `.ww` file is recursively folded into the importing unit and has no node, identity, interface, object, or link artifact of its own. Inline package blocks can also satisfy otherwise missing imports (C driver, lines 396–428 and 498–613). - A directory package selects all immediate `.ww` files except `*_test.ww`, sorts them by bytes, and has no target-specific selection rule (C driver, lines 239–301). The build path follows source symlinks while the test coordinator rejects them. - Resolution translates dotted imports to paths and performs a global directory-before-file search over the entry root, `-I` roots, and inferred source library. Thus a directory in a later root beats a file in an earlier root (C driver, lines 152–224 and 966–1003). - Every dependency emits source-like `.wwi`. Every importer receives the whole transitive `.wwi` closure, tagged with out-of-band module comments and prepended to a composed `.unit.ww`; the compiler reparses that unit (C driver, lines 702–809; [interface writer](../cmd/w6c/wwi.c), lines 1–24 and 505–570). - The root compiles without compiler `-I`, emits no `__root.wwi`, bypasses the dependency export-signature path, and receives special `main` handling; only dependency nodes emit interfaces. `ww test` also injects the resolvable `test` package as a synthetic root edge even when source has no such import, while runtime is an implicit link edge. Imports do not fully describe even today's complete graph (C driver, lines 1066–1083 and 1131–1146). - `.wwi` records exported prototypes and direct import text but no compiler, format, target, data-layout, object ABI, or runtime ABI identity. It includes non-semantic parameter names and import spelling. The compiler's `-I` flag both requests interface output and changes `main` symbol handling ([compiler entry](../cmd/w6c/main.c), lines 25–56 and 83–110). - For `P` reachable directory packages including root, a normal driver build launches `P` compiler processes, `P` assembler processes, and one linker. It writes `P-1` dependency archives itself. The link is root object, dependency archives in reverse topological order, runtime, then separately accumulated `-L` and `-l` values, losing their original interleaving (C driver, lines 1095–1249 and 1368–1460). - `-w DIR` is a caller-owned mutable reuse directory, not a cache. Freshness is exact composed-unit bytes, copied driver/compiler/assembler bytes, a text mode stamp, and artifact existence/nonzero size. The graph and units are rebuilt in memory and the final executable is relinked on every invocation. Publication through `.new` files with the unit committed last is usefully atomic (C driver, lines 867–952, 1016–1059, and 1110–1213). - Without `-w`, a build creates and deliberately retains `.sepwork`; repeating while it exists fails. With `-w`, the caller must create and serialize the directory. Normal driver products are always root executables linked with the runtime; there is no library-only product path, and `-S` merely stops after assembly. - `ww test DIR` delegates to a separate coordinator. It groups same-package `package p;` and external `package p_test;` tests from `*_test.ww`, excludes dependency tests, composes generated source roots, and parallelizes independent test binaries with deterministic reporting ([package coordinator](../internal/wwpackage/package.ww), lines 278–417, 508–648, and 725–1057). - Explicit `ww test FILE` bypasses the directory `*_test.ww` classifier and accepts an arbitrarily named source root. Universal directory packages delete that distinct test mode. - Current bootstrap is mixed C/self-hosted. Make keeps the C driver fixed, uses self-hosted compiler stages to produce `ww2`, `ww3`, and `ww4`, and compares `ww2 == ww3` and `ww3 == ww4`. The self-hosted driver itself is outside that fixed-point chain. The planned four stage-zero binaries are absent; the “no C compiler” route still uses host `ar` ([Makefile](../Makefile), lines 825–883; [bootstrap notes](../BOOTSTRAP.md)). ### 11.2 Conflated identities and accidental behavior This table records the baseline that the implemented slices below replaced; sections 11.6–11.18 are authoritative where they conflict with it. | Concept that must be separate | Current conflation or accident | |---|---| | package identity | Before the local-package slices, dotted import spelling was simultaneously graph key, module/symbol prefix, artifact basename, and link identity. The implemented loader now separates source spelling, expanded canonical identity, physical directory, and storage locator. | | declared name | Before section 11.18, imported directories required their declared name to equal the import-path leaf and `.wwi` retained only that leaf. The implemented compiler/export path now carries the declaration independently. | | filesystem location | Ordered search roots silently choose/shadow a location; the same physical directory may be compiled under two import identities, while duplicate locations for one spelling produce no collision diagnostic. Paths are lexical, not content identities. | | package versus file | Directories create separate-compilation nodes; files disappear into owners. The same `package` syntax means two compilation models. | | artifact versus identity | `.wwi/.s/.o/.a` names artifacts; root aliases to `__root`, which can collide with a real import. | | public versus non-semantic interface | Parameter names and AST-preserved type/import spellings influence `.wwi` bytes and reverse rebuilds. Imports/declarations are otherwise canonically sorted; whitespace/comments and original declaration order generally do not. | | compiler interface mode versus link identity | `w6c -I` both emits `.wwi` and classifies the package as a dependency for `main` mangling. | | native dependency versus linker search | Raw `-L` and `-l` names carry no selected file, ABI, order relationship, target, or content identity. | | cache location versus cache key | The explicit `-w` directory is both mutable namespace and freshness state; callers must serialize it. | | source root versus command UX | Help historically describes `.` like a basename file, while implementation stats and builds it as a directory. | Other accidental constraints include fixed 256/1024-byte name/path buffers. The compiler parser silently truncates dotted full imports beyond 255 bytes, while the C driver scanner can stop advancing and hang on an import identifier at that limit; the dynamically sized WWstage scanner differs. There is no regression test for this stage divergence. Compiler, assembler, and linker launches now use structured argument vectors in both stages. Both drivers honor exact executable paths in `WW_W6C`, `WW_W6A`, and `WW_W6L` and otherwise select their stage-specific sibling tools. Both drivers distinguish the package-source root selected by `WW_SRCLIB` from the runtime-artifact root selected by `WW_LIB`, and apply the same empty-value and repository/install fallbacks. The two implementations remain parallel production algorithms rather than one protocol implementation. Build and test disagree about source symlinks. External package tests are built from a generated single-file root plus `-I`; an external import of a multi-file production package can resolve and fold only its canonical same-named file rather than the directory package. Test work-directory names flatten `/` to `_`, so distinct lexical paths can collide. These are consequences of routing tests around, rather than through, one package model. `make install` copies only `ww`, `wwtest`, and `libwcc.a`, while the driver needs sibling compiler/assembler/linker tools and `libwwrt.a`; the installed result is not a self-contained functional toolchain outside the build tree. ### 11.3 Scaling, invalidation, and hidden inputs The driver performs deterministic linear action interning but now grows every package dependency vector dynamically (section 11.14). Every package compiler reads exactly one interface per direct dependency; transitive dependencies enter only the executable archive closure. Package compiler/assembler work within one driver remains serial; Make gains parallelism only by launching independent top-level driver builds. The observed invalidation rules are: - a private change in a directory dependency rebuilds that package and the unconditional final link, but not importers; - an exported change rebuilds direct importers and continues through an ancestor only while the regenerated direct-dependency export bytes change, stopping at the first byte-identical regenerated interface; - a private change in a folded file import rebuilds its entire owner; - a link-only option reruns the always-executed link but not package compiles; - changing copied compiler or assembler bytes rebuilds every package; and - nonzero corruption of `.s`, `.o`, `.a`, or `.wwi` may be accepted because content is not rehashed. Hidden or incompletely modeled inputs include `CC`, `AR`, `PATH`, `ccache`, Make flags, compiler built-ins, assembler/linker defaults, inferred `argv[0]` library locations, current working directory, file mode, runtime archive, linker binary, native-library resolution, host libc/CRT/loader, SDK, CPU, target, and environment. Make does not invalidate existing C objects when the host compiler or C flags change. Persistent package workdirs now bind the exact driver executable, conservatively covering its graph, unit, archive, and commit semantics; the remaining ambient inputs are not thereby promoted into a cache protocol. WW has no target triple, sysroot, conditional source, generator, manifest, lock, source digest, or frozen/offline concept. ### 11.4 Measurements and disposable experiments Measurements ran on Linux 6.12.76_1 x86-64 with eight logical CPUs, GCC 14.2.1, binutils 2.44, and no `ccache`. They used successful clean builds and isolated temporary source fixtures; no production migration was begun. Clean/full means use two timed samples and representative cold means three, without CPU isolation or OS-cache flushing, so they are observed baselines rather than universal performance claims. | Measurement | Result | |---|---| | clean `make all`, `-j1` | 24.847 s mean | | clean `make all`, `-j8` | 15.515 s mean; only 1.60× speedup | | warm `make all -j8` | 0.02365 s mean at Make level | | clean tool trace | 69 package compiles/assembles in six driver workdirs; 71 `w6c`, 76 `w6a`, six `w6l`, 63 in-driver archives; package work inside each driver stayed serial | | small / 8-package / 15-package cold driver build | 0.0103 / 0.1326 / 9.6706 s | | same warm driver builds | 0.00814 / 0.01347 / 0.05302 s; each still linked | | `out/` | 34,464,015 bytes, 398 files | | six WW build workdirs | 28,609,092 bytes, 351 files; 9,954,428 bytes (34.8%) duplicate beyond the first content copy | | 15-package root composed unit | 14 `.wwi` sections, 1,464,581 bytes; 62 interface insertions across graph, 1,928,898 composed-unit bytes versus 23,664 distinct interface bytes | A three-package `root -> mid -> leaf` fixture confirmed that root consumes both direct and transitive interfaces. A private leaf implementation edit rebuilt only leaf plus link. Adding a compatible public leaf API rebuilt all three even though `mid` emitted identical `.wwi`. A link-only `-L` change ran only the link. Switching the compiler executable by byte content invalidated all packages. Appending data to a nonzero cached `mid.s` was not detected; the old object was reused and the build succeeded. This directly rejects artifact-presence caching. Two builds from different absolute source roots produced the same 398 relative paths and all sampled WW-generated executables/package artifacts were byte identical. The full trees were not: 45 Cstage host objects/copied tools differed, including GCC `DW_AT_comp_dir`. Thus current checkout-independent byte identity holds for measured WW artifacts, not for the complete build. Cstage and WWstage drivers building the same eight-package graph produced a byte-identical final executable and all 38 non-tool artifacts, but took 0.138 s and 0.356 s respectively. The audit also found that Cstage formerly returned success after an ambient `chmod` lookup failed and left mode 0644, while WWstage created mode 0755 directly. Cstage now calls `chmod(2)` on the exact output path and reports failure, removing that host-tool and path-splitting asymmetry. ### 11.5 What survives and what is deleted The replacement retains these sound concepts: - explicit source imports, package clauses, exported/private declarations, and loud directory-package-cycle errors, strengthened to every package after file folding (whose cycles were merely visit-deduplicated) is deleted; - directory package boundaries, made universal rather than optional; - same-package and external `*_test.ww` semantics, dependency-test exclusion, deterministic discovery/reporting, and always executing selected tests; - deterministic sorting/serialization, atomic artifact publication, fixed-point bootstrap checks, and byte-identity tests; and - the ordinary `ww build`, `run`, and `test` user experience. The replacement deletes these concepts rather than emulating them indefinitely: - file imports, inline multi-package units, bare dotted imports, `-I` search roots, directory-before-file precedence, and the `__root` artifact alias; - `.wwi`, `//ww:module` wrappers, `.unit.ww`, transitive interface prepending, source-prototype interchange, automatic per-dependency archives, and `-w`; - raw ambient `-L`/`-l`, compiler/linker/sysroot defaults, and build-time `pkg-config` discovery; - separate C and self-hosted production drivers, the production Make graph, and the separate source-composing test coordinator; and - the current Cstage bootstrap path and permanently owned assembler/linker after the generated C seed and pinned external tool closure replace them. There will be no compatibility alias that silently translates an old import, interface, workdir, or link search into the new model. ### 11.6 Implemented local package slice The first executable package slice is intentionally smaller than the final module design above. It is local, offline, and manifest-free. The supported form is: ```sh out/bin/ww build -I /work/acme -o app /work/acme/cmd/app ``` Every selected source uses the existing syntax: ```ww package main; import lib.math; ``` A source import is translated from dots to path separators, expanded through the nearest eligible local `vendor` directory described in section 11.16, then falls back to directory lookup through the entry package's directory, explicit `-I` roots in command order, and the toolchain source-library root. A same-named `.ww` file is neither a match nor a shadow for an import, so a later root containing the directory wins over an earlier file decoy. There is no network, manifest, or imported-file fallback. Explicit single-file CLI roots retain their raw-unit compatibility path. The loader uses the compiler frontend's imports-only parser, retains every real import occurrence with its owning source file and position, byte-sorts and deduplicates the resulting canonical direct edges, interns canonical directory actions, and reports self-imports and stable cycle chains before compilation. Occurrence retention makes contextual `internal` and `vendor` checks run at every import site; it does not duplicate package actions or compiler inputs. A directory package consists of its immediate `.ww` entries whose basenames do not begin `.` or `_`: regular files and symlinks targeting regular files are included under the entry name, while symlinks targeting directories are ignored. The production variant excludes `*_test.ww`; each variant retains byte-sorted filename order. Every selected production file must declare the same package name, but that declaration is independent of the directory name and every component of the canonical import path. A selected command directory declares `package main` while retaining its complete canonical import identity. A source import of a command package from a different directory is rejected; the one same-directory exception is an external `main_test` variant's canonical import of its effective augmented test action. Two ordinary logical identities for one physical directory are rejected rather than compiled twice; section 11.16 records the deliberate exception for distinct expanded vendor routes that converge through symlinks. Packages compile serially in dependency-first postorder. The compiler emits the existing deterministic `.wwi` interface for every directory-package action, including an executable root. Its primary section contains that package's byte-sorted direct imports and exported declarations. The compiler then appends byte-sorted, origin-tagged sections for only the foreign type and constant facts recursively reachable from the primary public signatures. Reachable owner-local private nominal types are carried without `export`: they make the export self-contained for type checking, but qualified source lookup still rejects their names. Checked fixed array dimensions are emitted as numeric type facts, so a public layout never requires exposing the private constant spelling that produced its length. A package compilation unit contains only that package's own byte-sorted sources, deterministic `//ww:module-reset` separators, and sorted driver-private resolution metadata; it never contains a dependency source body. Each **direct** import is a separate `--import ` compiler input, sorted by canonical path and deduplicated by the loader; a source spelling expanded through `vendor` additionally receives the non-dependency `--import-map` described in section 11.16. No transitive `.wwi` is passed. Origin-tagged facts inside those direct artifacts are compiler data, not source imports: a source qualifier is visible only in the source file that directly imports it. The qualifier is the imported export's declared package name, not the source spelling or import-path leaf. Private members, transitive-only qualifiers, bare values, and bare types remain compiler errors. In `-c` package mode the compiler parses each export independently, then coalesces repeated exported type/constant facts with the same origin, kind, and name, preserving one nominal type identity across diamonds; raw non-package `w6c` retains its existing one-source behavior. The source-like `.wwi` syntax remains a transitional export encoding pending the binary `.wwe` format described above, but the separate direct-input ownership boundary is live in production Cstage and WWstage compilers and drivers. A selected production root is one normal package action. Its finalized canonical import identity tags its owner-only unit; it receives only direct exports, emits `.wwi`, `.o`, and a deterministic `.a`, and is compiled exactly once. The declared package name is semantic package content but never validates, shortens, aliases, or replaces that identity. After loading and identity finalization, the declaration also selects the terminal build action: `package main` is a command and every other valid declaration is a compile-only library. A command root receives the narrow compiler `--entry` flag, which controls bare `main` codegen, then the linker receives that root archive first, the complete reachable package-archive closure, and the runtime archive; it never receives `.wwi`. A non-main root receives no `--entry` and never enters the linker. `main` validates command kind but never replaces or truncates an identity such as `cmd.tool`. The explicit package-less single-file compatibility path has no directory package declaration to classify and remains a raw command unit; it does not participate in canonical directory-package interning. The package driver still uses the parser-only `--command-package` marker for command test variants that must remain ordinary archive code. Neither marker changes export identity, and imported interfaces retain independent canonical owner and declared-name records. The linkers seed `main` before archive selection, so the existing WWAR member protocol needs no special root object or format change. Publication is separate from that semantic action choice. `ww build -o lib.a DIR` or `ww build -I ROOT -o bar.a foo.bar` automatically publishes a non-main root's deterministic archive and self-contained compiler export at `FILE.wwi`, without invoking the linker; the latter retains `foo.bar.*` symbols. Without `-o`, a non-main root and its dependencies are compiled in the selected scratch or persistent work directory and no cwd product is invented. For a command, `-o` continues to name the executable publication path. Output names, request order, and whether publication was requested never enter package or action identity. The historical action-selecting `-p` exception is removed and rejected as an unknown build flag. Assembly-only `-S` still stops before object, archive, publication, or link production. A literal directory is reverse-resolved through the active source roots or receives the deterministic local identity described below; its declaration can never invent or truncate that identity. Two cold builds with identical inputs are required to produce byte-identical requested products. Compiler intrinsics keep their package-mode runtime ABI independent of transitive source interfaces (for example, `alloc` lowers to the runtime allocator without requiring an `rt.wwi` compiler input). This rule follows the pinned official Go 1.26.5 source at commit `c19862e5f8415b4f24b189d065ed739517c548ba`. `go/build.Package` stores source directory, declared name, and import path independently, and defines a command solely as a package named `main` ([`go/build/build.go`, lines 436–449](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L449), [`go/build/build.go`, lines 514–519](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L514-L519)). The Go builder's `AutoAction` links only `main` and returns the archive compile action for every other package ([`cmd/go/internal/work/action.go`, lines 450–456](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L450-L456)). The build command invents a default output only for one `main`, applies an explicit `-o` to either AutoAction result, and otherwise builds each requested package without conflating publication and semantic kind ([`cmd/go/internal/work/build.go`, lines 473–478](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L473-L478), [`cmd/go/internal/work/build.go`, lines 508–548](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L508-L548), [`cmd/go/internal/work/build.go`, lines 551–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L551-L558)). Both WW stages represent the rule with the existing loaded declaration and stable root action index; no package, dependency, ownership, locator, traversal, or closure allocation is added. `ww run` adds only a command-kind requirement: a successfully loaded, cycle-free non-main root produces the deterministic `package PATH is not a main package` diagnostic before any compiler, assembler, or linker invocation; package and graph failures retain precedence. Before a non-main `-o` build invokes a producer, both stages validate the longest atomic publication spelling, `FILE.wwi.new`, so an incomplete archive/export pair is never caused by a late path-overflow failure. Package loading, cycle detection, and closure validation retain diagnostic precedence over this publication-only check, and `-S` does not validate a publication path it never consumes. Build workdir format 14 and test workdir format 13 invalidate older unit vouchers before reuse because source binding and vendor-directory identity now participate in compiler argv and persistent unit semantics. Thereafter an equivalent warm library build invokes no tools, a private dependency change stops at its unchanged export, and an export change recompiles its direct importer under the existing propagation rule. ### 11.7 Implemented directory package-test slice Directory tests now enter that same local package loader and build path. The supported manifest-free forms include `ww build DIR...`, `ww build DIR/...`, `ww test DIR...`, and `ww test DIR/...`, with overlapping direct and recursive roots. Test retains its existing `-run`, `-filter`, `-list`, `-timeout-ms`, `-j`, `-c`, and `-w` forms. `ww test -c -o test.bin DIR` names the result when the request selects one canonical directory, including a directory with both same-package and external-package test sources. The coordinator rejects one output name only when it would fan out over multiple directory products. Explicit `ww test FILE` retains its compatibility path. The test coordinator still discovers requested directories, classifies the selected test package names, executes one binary per test-bearing canonical directory, and emits captured results in byte-sorted directory order. It no longer concatenates a generated production/test root, resolves imports, or starts one package graph per declared test package. Instead it sends one ordered build request containing one product descriptor per selected directory, with optional production, same-package, and external-package selectors, to the Cstage or WWstage command. It also carries output destinations, coordinator-private completion paths, import search roots, and the optional command-scoped work-directory policy. The command owns source selection, package loading, substitution, compiler inputs, archive construction, the single generated main, and linking: - The ordinary production action selects the directory's byte-sorted non-test files. A no-test request uses this action directly. Ordinary builds and dependencies outside a tested closure continue to use it. - The internal production-plus-test variant selects the byte-sorted production files followed by byte-sorted matching `package p` test files. It is distinct from production, exports declarations contributed by internal test files, and replaces the ordinary action throughout the applicable tested closure. - When production sources establish `p`, the external variant selects only matching `package p_test` files, where `p` is the production declaration rather than an import-path leaf. A test-only directory may establish its own `p`, `p_test`, or valid `p`/`p_test` pair, matching pinned `go/build` classification. The external action's import of the package under test binds to the augmented internal action when it exists. Importers affected by that replacement are copied and rewired transitively; an ordinary and augmented instance of one canonical package never coexist in the linked test closure. - Generated main is a separate package action whose owner-only generated unit declares `package main` and imports every applicable internal/external target plus test support. It consumes those direct `.wwi` files, emits its own `.wwi/.o/.a`, and alone receives compiler `-T --entry`. Repeated byte-sorted `--test-target-package ` arguments identify the target set. Those compiler-private canonical qualifiers prevent declared-name collisions; they are not user alias syntax. The coordinator groups one test product by canonical directory, but physical location is not a compiler/package identity. The authoritative action key uses the finalized canonical dotted import identity, semantic variant, role, and, for a copy made by recompile-for-test, the owning canonical directory product's stable test identity. The semantic variants are production, production-plus-same-package-test, external `_test`, directory generated main, and recompiled-for-test. The declared package name, local import binding, request spelling, path leaf, source filename, artifact basename, product ordinal, output path, and discovery order are presentation or source-location state and never substitute for that key. A literal directory root may enter the interner before its full import spelling is known. It is provisionally interned by canonical directory and variant, and a later source import of that directory binds and reuses the provisional action. After all source discovery, but before generated-main construction or any tool invocation, each still-unbound directory is finalized by this exact algorithm: 1. For every import-resolution context that reached the directory, walk that context's roots in its normal forward precedence: the selected package's directory, explicit `-I` roots in command order, then `WW_SRCLIB` or the selected toolchain source root. A request pattern never becomes an import root and therefore cannot shorten, replace, or donate package identity. 2. Canonicalize each candidate root and require the package directory to be a strict descendant. Every relative path component must be a non-keyword WW identifier. Convert separators to dots, then resolve that relative spelling again through the complete ordered context. Accept it only if ordinary forward lookup selects the same canonical directory. Thus an earlier shadow invalidates a name inferred from a later or nested root. 3. Bind the first precedence-valid candidate from each reaching context through the command-global bidirectional interner. An identity supplied by successful logical package lookup, such as `encoding.utf8`, is already bound and is preserved exactly. That forward-selected identity is authoritative: reverse derivation applies only to still-unbound literal roots, so a nested active root cannot rename an explicitly resolved package. 4. If no active root can represent the directory, bind the reserved, non-source-importable identity `__wwlocal.p`. The escape is injective and reversible over path bytes: ASCII letters and digits are copied, `_` becomes `_u`, `/` becomes `_s`, and every other byte becomes `_xHH` with lowercase hexadecimal. Source imports of `__wwlocal` or any of its children are rejected, so this command-local identity creates no alias. The selected full identity is never validated against the ordinary declared package name. Production and internal variants retain the production declaration; when production exists, an external variant is admitted only as `_test`. A test-only directory instead establishes one consistent test package declaration itself. The one command-kind rule is that a selected command family declares `main`/`main_test` while keeping the finalized ordinary identity unchanged. A source import of that command from another directory rejects as a program before tools; a colocated external command test may reuse the canonical production action. There is no fallback from an empty import path to a declaration name. Relative, absolute, and symlink spellings converge through the canonical directory; two unrelated local directories with the same declaration therefore remain distinct. One bound import path mapping to two directories and one directory acquiring two incompatible ordinary import paths are command-global deterministic errors before any compiler, assembler, archiver, or linker ambiguity. The same check spans variants: an external action cannot hide a different directory's production package behind its derived `_test` compiler path. The derivation and diagnostics are implemented symmetrically in `cmd/ww/main.c` and `selfhost/cmd/ww/main.ww`. The package coordinator in `internal/wwpackage/package.ww` supplies canonical selected directories and variant descriptors, preserves an explicitly resolved identity only for one direct request, and forwards a caller's `-w` semantic-action store unchanged. It never derives identity or persistent layout from a pattern traversal prefix and does not add that prefix to import search. `w6c` and `wcc` consume the finalized dotted identity as export/symbol owner while reading the declared name independently from export data; neither tool performs directory lookup or introduces a package registry. Artifact publication follows the semantic action instead of product order: production uses the full finalized ordinary identity, internal appends `-internal-test`, external appends `_test-external-test`, and the one directory-owned generated main appends `-test-main`. Its package identity is `__wwtestmain..main`, independent of either declared test name. Equivalent roots therefore converge on one directory product and reuse already interned actions and persistent-workdir slots regardless of discovery or request order. The narrow raw single-file compatibility path alone retains `__root`. A deterministic dependency-first traversal of the complete command union invokes the compiler, assembler, and in-driver deterministic archiver once per interned action. This is compile-time interning, not linker-argument deduplication. Each canonical directory product is linked once from its single generated-main root archive and the complete reachable archive closure. The shared plan remains package-test-specific; it is not a generalized scheduler, action schema, cache, or protocol. Each selected directory retains the ordinary entry-directory-first resolution context from the local package slice: its directory, explicit `-I` roots in command order, then the toolchain source root. Same and external variants of one directory share that context; unrelated directory roots never acquire lookup precedence from their request order. When multiple contexts reach one canonical production package, the loader verifies that every directory import binding is identical before reusing its compile action. A different binding is a deterministic package-resolution failure for the roots that reach it, rather than a first-root-wins build. A production action failure is attributed to exactly the roots that reach it, but the complete command is one publication transaction. The driver may continue enough of the already validated plan to retain deterministic action and product diagnostics, but one failed producer, linker, status stage, or commit suppresses every new action voucher, tool record, product, and status from that request. The coordinator therefore runs no sibling test binary from a rejected union build. After one successful union build, the completed test products share the coordinator's existing `-j` process bound; captured output is still emitted only in byte-sorted directory/package order. Ordinary production loading never selects dependency `*_test.ww` files. Imports that occur only in selected test files add edges only to the applicable internal or external action. Recompile-for-test may create a product-scoped copy of an ordinary transitive importer, but that copy retains the importer's production source unit and changes only canonical dependency targets. Each compiler unit contains only its action's owned source set, while its invocation receives only the byte-sorted direct dependency `.wwi` artifacts as separate inputs. Variant compiles receive `--test-package`, which validates and retains private `@test` declarations as compiler-only export metadata without synthesizing an entry point. The distinct directory generated-main action consumes that metadata from every direct target export and synthesizes one dispatcher with `-T`. The generated-main action, rather than the tested variant, owns the implicit direct test-runtime support edge. The command-scoped plan compiles the common support production package once for the complete test request. The command resolves that edge from the selected toolchain source tree, not the user search path; the support package's own imports are also loaded in that toolchain context. Normally its graph qualifier is `test`, so an explicit source `import test` coalesces with the same canonical package. When a real user package occupies that identity, the command presents the runtime edge to the compiler under the reserved `__wwtest` qualifier. This keeps a production package named `test` available to external tests. Explicit raw single-file `ww test FILE` fixtures retain the narrow fused `-T` compatibility path because an anonymous multi-package raw unit is not a canonical directory package; that path still consumes support as a direct export and emits a root `.wwi/.a`. The reserved support action and an ordinary source-imported package `test` may coexist only because the former is explicitly rebound to the compiler-only qualifier `__wwtest`. This is the sole role-based directory alias and cannot be created by a source import. The separate expanded-vendor-route exception in section 11.16 is canonical source-tree identity, not a role alias. All ordinary and test actions use canonical action identity and the global bidirectional import-path checks above. External self-import substitution changes the target action, never the source spelling or file-local binding. There is no role-based tolerance for duplicate ordinary import identities and no late product-closure ambiguity to resolve. Production, internal, and external actions may select source from one physical directory, but the final directory test closure is strict: wherever the augmented internal action substitutes for production, every affected direct and transitive edge is rewired before tools. A closure containing both ordinary `p` and its augmented `ptest` is rejected rather than hidden by initialization or linker filtering. The external action therefore sees internal-test exports through `ptest`, and the one linked process owns exactly one package state. Variant-only archives never leak into an unrelated directory product. All ordinary logical and physical package-identity collision checks remain unchanged; only distinct expanded vendor routes receive the section 11.16 symlink-convergence exception. Both stage linkers receive the generated-main archive first, followed by the complete reverse-topological reachable package-archive closure, runtime, and explicit `-L`/`-l` values through a structured argument vector. No `.wwi` or special root `.o` appears in linker argv, and no fixed flattened command buffer can truncate a large closure. WWstage emits joined `-Ldir` and `-lname` arguments accepted by its native linker, while Cstage preserves the equivalent split forms. Generated artifact paths are bounds-checked before any unit is opened, so distinct root keys cannot alias by truncation. Recursive discovery groups by physical directory before sorting filenames, and one stable escape of the canonical discovery directory names the persistent command work directory. It contains neither a declared package leaf nor a product ordinal, so equivalent path spellings and reordered products select the same request state. Every selected `*_test.ww` package variant is built even when its files only declare helpers and contain no `@test`, so its package clause and imports are still checked; that is a real zero-test package and runs one empty combined harness. A directory with no selected test files instead follows the no-real-run path: validate/compile ordinary production as needed, publish status only, and create no support action, generated main, link, binary, result, or process. The coordinator alone emits its `[no test files]` report. Persistent workdirs keep a global driver/compiler/assembler/stamp identity and per-action committed units. When that global identity is stale, the command forces every requested action cold while preserving the complete old generation as rollback state. New tool records, artifacts, units, products, statuses, and the new stamp become visible only in the request-wide commit after every product has staged successfully. A rejected request leaves the old generation byte-identical, and a retry cannot reuse any uncommitted work from the rejection. Warm reuse compares the staged owner-only unit, committed artifacts, and the actual bytes of each direct dependency export. A changed shared dependency is compiled once; its direct importers are reconsidered once; and propagation stops as soon as a regenerated importer export is byte-identical. Stable semantic artifact keys make that behavior independent of which ordinary or test product first discovered the action. The completed topology and its pinned Go 1.26.5 evidence are specified in section 11.22. WW borrows that command-global action boundary without adding Go's build cache, import-configuration format, or module system. ### 11.8 Implemented exact package-tool invocation slice The local package builder now launches the compiler, assembler, and linker as an executable plus an argument vector in both Cstage and WWstage. No package source path, work-directory artifact path, output path, test-support qualifier, or link-closure member is flattened into a shell command. Paths containing spaces therefore retain one argument boundary from the package coordinator through compilation, assembly, and final executable linking. `WW_W6C`, `WW_W6A`, and `WW_W6L` each name one exact executable path. They are not shell fragments and are not searched through `PATH`. With no override, Cstage keeps its `w6c`/`w6a`/`w6l` siblings and WWstage keeps its `w6c_ww`/`w6a_ww`/`w6l_ww` siblings. The coordinator preserves these variables when it starts the one command-scoped package build, so the same contract covers ordinary directory builds, same-package tests, external tests, recursive test requests, and persistent-workdir tool identity. A failed overridden compiler or assembler remains attributed to its owning package in both stages. The Cstage linker also sets executable mode with `chmod(2)` on the exact output path rather than invoking an ambient command. Source imports still own the graph, each directory is still one production package, compiler actions receive direct dependency exports as individual arguments beside an owner-only `.unit.ww`, and links receive the complete per-root `.a` closure. Repository-native coverage wraps all three real stage tools at executable paths containing spaces, records every argument boundary, inspects `.unit.ww`, `.wwi`, `.a`, and root archive placement, runs the published binary, compares repeated Cstage/WWstage artifacts and traces, and removes one direct export at compiler entry to compare package-attributed diagnostics. Go 1.26.5 keeps the same responsibility boundary: its work executor passes the selected compiler or linker tool and a constructed argument slice to the builder, while package loading and action construction remain separate ([`cmd/go/internal/work/exec.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/exec.go)). WW adopts that exact-tool boundary without adding a command schema, generalized action graph, scheduler, manifest, cache protocol, or package-manager behavior. ### 11.9 Implemented package and runtime library-root parity slice Cstage and WWstage now apply the same two-root contract. A nonempty `WW_SRCLIB` selects the toolchain package-source search root. It is appended after the entry directory and explicit `-I` roots for every package context, and compiler-generated test support is resolved from that toolchain root rather than from a user package that happens to have the same name. A nonempty `WW_LIB` independently selects runtime artifacts; executable and test links use `$WW_LIB/libwwrt.a`. If that archive is absent, both stages pass their sibling `start.o` and `syscall.o` runtime objects instead. Missing and explicitly empty values use the same deterministic fallbacks in both stages. Bare logical build and run targets search the current directory, explicit `-I` roots, then one selected library root. That last root is a nonempty `WW_SRCLIB`, else a nonempty `WW_LIB`, else an existing `/../../lib`, else an existing `./lib`, else `/../lib`. Once a target is resolved, its import graph retains the ordinary entry-directory-first context and its separate source-root policy: without `WW_SRCLIB`, that policy prefers the repository and `./lib` source trees before falling back to the runtime root. This preserves Cstage's existing distinction between locating a requested package and selecting the toolchain source tree used by that package's imports. The variables select local directories only. They do not add manifests, dependency declarations, network lookup, package-manager behavior, or a second graph: source `import` declarations still create every language edge, resolved directories still intern to canonical package identities, compilers still receive only direct `.wwi` exports, and final links still receive the complete reachable `.a` closure. Directory tests continue to build same-package and external-package variants through the same command-scoped package universe. Repository-native coverage uses distinct source and runtime roots whose paths contain spaces, resolves a bare logical target found only through `WW_SRCLIB`, places a same-named decoy under `WW_LIB`, records exact compiler, assembler, and linker arguments, inspects `.unit.ww`, `.wwi`, `.a`, diagnostics, binaries, and runtime results, and compares both stages. It separately exercises the runtime object fallback and explicitly empty variables. The package-test observer copies the toolchain source library to a selected root, marks the compiler-generated test-support source, and proves that both the marker and the selected runtime archive reach real same-package test builds through the coordinator. The ownership boundary follows the pinned Go 1.26.5 implementation: source headers supply imports in [`go/build/read.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/go/build/read.go#272), the loader canonicalizes and reuses packages in [`cmd/go/internal/load/pkg.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/pkg.go#633), tests remain real package variants in [`cmd/go/internal/load/test.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/load/test.go#85), and direct compile dependencies are expanded separately for linking in [`cmd/go/internal/work/action.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/action.go#628). ### 11.10 Implemented persistent-workdir driver identity slice The package driver is now an explicit content input to every persistent `-w DIR` package action. Both stages copy the exact invoking executable to `.wwtool.ww`, alongside `.wwtool.w6c`, `.wwtool.w6a`, and the mode/format stamp. A warm invocation byte-compares all applicable live executables before considering any committed unit reusable. A missing or changed driver copy invalidates every `.unit.ww` voucher before compilation; old artifacts may remain recoverable, but none can be reused without a freshly committed unit. That slice introduced workdir format revisions 8 for ordinary builds and 9 for tests. Later package-identity slices supersede those revisions; the current formats are recorded in section 11.16. This closes a real hidden-input boundary. The driver, rather than `w6c`, owns canonical directory interning, source-derived graph construction, owner-only unit composition, direct-export argument construction, deterministic dependency ordering, single-member package archive serialization, and the artifact commit sequence. Unit equality alone cannot identify changes to those algorithms, and a manually maintained format number can be forgotten. Exact driver bytes conservatively cover them during the transitional plain-file reuse scheme. This may rebuild after an unrelated driver change, but it cannot falsely reuse a package after a relevant one. The linker remains outside the recorded package identity because persistent reuse never skips a final link: each invocation reconstructs the complete reachable `.a` closure, selects current runtime inputs and link flags, and runs the selected linker. Thus a linker or runtime change affects the requested binary immediately without forcing unrelated package compilation. Repository-native coverage runs a three-directory import graph through copied, independently mutable Cstage and WWstage drivers. Exact compiler, assembler, and linker wrappers prove a cold dependency-first build, an unchanged warm compile/assemble skip with a deliberate relink, and full package invalidation after only the invoking driver's bytes change. The test inspects owner-only `.unit.ww` inputs, separate direct `.wwi` arguments, `.a`, identity files, transitive link order, diagnostics before tool execution, published binary bytes, runtime exit, and stage equivalence. Go 1.26.5 draws the same semantic line with a richer cache: its build action ID binds compiler/assembler tool identities, configuration, selected source content, and direct dependency content IDs in [`cmd/go/internal/work/exec.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/exec.go#261), while its link action ID separately binds linker configuration and the package closure in [`cmd/go/internal/work/exec.go`](https://go.googlesource.com/go/+/refs/tags/go1.26.5/src/cmd/go/internal/work/exec.go#1504). WW adopts only the correctness boundary in its existing inspectable `cmp`-based workdir. It does not add build IDs, hashes, a CAS, an action graph, a scheduler, or a manifest. ### 11.11 Implemented directory-only source-import slice Cstage and WWstage now use directory packages for every parsed source import, including imports selected only by a package-test variant and real imports in the test-support package. Source imports first probe the bounded vendor candidates in section 11.16, then make one ordered fallback pass for `//`; they never probe `/.ww`. The compiler-generated edge to test support remains synthetic. Unit composition consequently writes only the owning package's byte-sorted source files and never copies a dependency interface or imported source body. Missing imports retain the importing source position and the same stable diagnostic in both stages. Root selection remains a separate compatibility boundary. A literal `.ww` CLI target, or a bare CLI target found as `/.ww` after the global directory search, can still create one raw single-file root. Its historical inline package clauses may satisfy compiler-fixture bindings inside that raw unit. Directory roots cannot use that exemption, and no filesystem source import can reach it. This preserves low-level compiler fixtures without weakening package-graph identity. The self-hosted tools no longer depend on the removed behavior. `w6a/` and `w6l/` are executable `package main` directories whose sorted source sets are compiled once. The compiler backend is one `wcc/` directory package with a narrow exported check/codegen façade; `w6c` and `wwdump` import that package from its parent search root instead of importing its implementation files. Legacy test fixtures were converted to directories, except for one intentional compiler leaf-collision probe that now invokes `w6c` on an explicitly composed raw unit. The Lisp example likewise imports a `lispcore/` directory package. The focused native regression puts only `example/foo.ww` in an earlier import root and a two-source `example/foo/` package in a later root. Both stages select the directory, emit the exact sorted package-owned unit, consume its direct dependency export, produce byte-identical deterministic `.wwi` and `.a` artifacts, link and run a transitive archive closure, and repeat the resolution through a real directory-package test. With only the file root present, both stages reject the import with byte-identical package-attributed stderr. The existing exact-tool observer remains the non-duplicated proof that each canonical production action compiles once, compiler units contain only owned sources, compile argument vectors contain exactly direct `.wwi` inputs, and linker vectors contain the complete reachable `.a` closure and no `.wwi` path. ### 11.12 Implemented direct compiler-export input slice Cstage and WWstage now share one small package-compiler convention: `--import ` may repeat before the one owning source unit. It is valid only with `-c`; paths must be nonempty, strictly sorted, and unique. Both compilers read and parse every export independently under the supplied canonical identity before parsing the owner unit, then pass the merged semantic declaration list through the existing checker, deterministic export writer, and primary-only code generator. Missing export bytes therefore fail at the compiler boundary as `w6c: import : cannot read `, followed by the driver's stable owning-package attribution. No import configuration file, manifest, schema, package database, or network lookup is involved. Both drivers construct those arguments directly from the package node's sorted, deduplicated outgoing edges. They never walk grandchildren for compilation. Every `.unit.ww` contains the node's byte-sorted source files, reset separators, and any sorted driver-private vendor/import-map voucher comments, but no dependency body. When exact source spelling differs from a selected expanded canonical identity, the drivers also pass sorted, unique `--import-map ` triples. A map must target an ordinary direct `--import`; it adds no export input or graph edge. The compilers rewrite only the matching primary import's canonical semantic key before merging interfaces. They then obtain that target's declared package name from its direct export and install it as the default qualifier in the owning source file. Source spelling and position remain intact; generated/synthetic imports use their explicit compiler-owned bindings. Executable linking independently walks the full reachable package closure and passes archives, never interfaces. The same path handles an ordinary package, the production-plus-internal-test variant, the external test package and its effective production-or-augmented self dependency, compiler-generated directory test main, and the reserved test-support package. Persistent workdirs compare a newly emitted export with its committed predecessor before allowing a direct importer to reuse owner-identical artifacts, retaining correctness without a new cache schema or identity record. The canonical-root regressions additionally prove the following in both stages: a literal root under one import root publishes its complete dotted identity; logical, literal absolute, equivalent, relative, and symlink routes emit byte-identical `.unit.ww`, `.wwi`, and `.a`; root-only and combined root/import requests emit those same bytes; dependency-first and root-first discovery each compile the shared production action once; recursive `a/foo` and `b/foo` directories declaring the same `package foo` publish distinct `a.foo` and `b.foo` variants; and two outside-root `package foo` directories coexist in one command under distinct reversible local identities. Equivalent recursive spellings reuse the same persistent semantic-action store without new compilation, while source imports of the reserved local namespace reject before tool invocation. The exact-argv command root declares `package main` but keeps its non-`main` canonical identity in the unit, export, archive, compiler argv, and linker argv; the bootstrap self-rebuild independently proves the same rule for the real `w6a` and `w6l` command directories. A focused command-test row proves distinct production, internal, external, and generated-main actions, colocated external-to-augmented substitution, parser-only command markers, stage-equal unit/export/archive bytes, the one combined test binary's runtime behavior, and pre-tool rejection when another directory tries to import the command. The exact-argv regression uses the real diamond `base -> {left,right} -> root`. It proves one compile per node; no input for `base`; only `base.wwi` for each middle node; only sorted `left.wwi` and `right.wwi` for `root`; exact owner-only unit bytes; the complete four-package link closure including the root archive; no link-time `.wwi`; exit status 42; and byte-identical units, exports, archives, executables, and tool argument vectors across two clean Cstage builds and two clean WWstage builds. The existing directory-package variant regression checks separate production, internal, external, and directory-generated-main actions, exact generated-main direct target/support exports, canonical recompile-for-test substitution, and one archive-only link closure. It also reverses equivalent product descriptors and compares exact compiler and linker trace bytes, then changes a shared direct export in persistent workdirs to prove propagation through direct importers stops at the first byte-identical regenerated export. Both stages compile and run those actions with owner-only units and byte-identical artifacts. The pinned official Go 1.26.5 tag (commit `c19862e5f8415b4f24b189d065ed739517c548ba`) supplies the design boundary: - `go/build` represents one selected directory package with its import path, package name, ordinary files, internal-test files, external-test files, and their imports ([`build.go`, lines 436–493](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L493)). Those fields remain separate in Go; WW's final-component/name equality is its existing language validation layered on the canonical identity, not a claim that Go conflates `Name` with `ImportPath`. Its directory reader is required to return name-sorted entries ([lines 108–111](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L108-L111)), and local directory loading reverse-derives a complete import path by checking `GOROOT/src` first and then `GOPATH` roots in order. A candidate under a later root is rejected when the same relative path resolves through an earlier root to another directory; an outside-root directory remains without an ordinary import path ([lines 612–665](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L612-L665)). Forward import lookup selects one directory in search order ([lines 725–767](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L725-L767)), and the selected directory alone is scanned ([lines 859–913](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L859-L913)). The sorted scan assigns each accepted source to that package's ordinary, internal-test, or external-test list ([lines 948–1036](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L948-L1036)). - `cmd/go/internal/load` derives an outside-root local directory's deterministic pseudo-import path from its slash-form absolute directory and establishes the package-data cache/promise boundary around that resolved key ([`pkg.go`, lines 633–647](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L633-L647)). WW uses the same reserved full-directory principle but a reversible byte escape, strengthening it so two canonical directory spellings cannot collapse merely through character sanitization. The Go loader expands source imports before recording their canonical paths ([`pkg.go`, lines 658–669](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L658-L669)). It resolves canonical path and directory before consulting the package-data cache ([lines 833–842](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L833-L842), [lines 863–911](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L863-L911)), and the command-global package cache returns the existing package pointer for a later root or import of the resolved identity ([lines 757–775](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L757-L775)). Go keeps a command-line `Name == "main"` package as the selected command and rejects an import from a different directory, while permitting the same-directory test-loader edge ([lines 799–805](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L799-L805)). The package's parsed import list becomes its direct package dependencies, rather than a transitive flattening ([lines 433–440](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L433-L440), [lines 2024–2047](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2024-L2047)). - `cmd/go/internal/work` keys its action cache by operation mode plus package pointer ([`action.go`, lines 202–206](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L202-L206)) and returns the already-interned action for that key ([lines 437–447](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L447)). A selected package whose independent `Name` is `main` receives a link action ([lines 450–455](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L450-L455)) while retaining its ordinary compiled archive action. A compile action depends on only `p.Internal.Imports` ([lines 628–658](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L658)); an executable link asks for that same cached root compile action ([lines 919–957](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L919-L957)) and separately expands the complete transitive link closure ([lines 1034–1068](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L1034-L1068)). - The work executor derives compiler package mappings from those direct build dependencies ([`exec.go`, lines 864–884](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L864-L884)), compiles the package's own source list to `_pkg_.a` ([lines 928–935](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L928-L935)), packs and publishes that package archive ([lines 1017–1033](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1017-L1033)), and links the compiled main archive with mappings for every dependency already expanded onto the link action ([lines 1592–1624](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1592-L1624), [lines 1635–1647](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1635-L1647)). - Go's test loader explicitly models production, internal production-plus-test, external `_test`, and generated main, and states that `ptest == p` when production can be reused ([`test.go`, lines 85–102](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L85-L102)). Test imports use the ordinary load cache and compare canonical `ImportPath` ([lines 118–161](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L118-L161)); the internal copy is created only when needed ([lines 175–226](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L175-L226)), while external and generated-main packages remain distinct ([lines 228–293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L228-L293)). Generated main receives its direct support and selected-variant imports ([lines 307–358](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L307-L358)), and copy-on-write rewriting preserves the original package pointers/actions for unaffected importers ([lines 421–472](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L421-L472)). - Unified export production begins from the local package, re-exports required dependency data, and prunes unnecessary detail ([`unified.go`, lines 147–168](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/unified.go#L147-L168)). It type-checks the package's parsed sources and writes deterministically ordered public/private roots ([lines 314–362](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/unified.go#L314-L362)), then finalizes self-contained export data with sorted relocated declaration and body indexes and a fingerprint ([lines 463–570](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/unified.go#L463-L570)). - Compiler import handling canonicalizes each source import and rejects self import ([`import.go`, lines 125–167](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/import.go#L125-L167)), then independently opens and decodes each direct package archive/export ([lines 170–225](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/import.go#L170-L225)). The complete unified section and linker fingerprint are read from that selected package file ([lines 229–296](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/import.go#L229-L296)). `ReadPackage` reconstructs a package from its public export root ([`ureader.go`, lines 28–62](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/importer/ureader.go#L28-L62)), interns embedded package descriptors by canonical path and restores their import lists ([lines 152–196](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/importer/ureader.go#L152-L196)), and reconstructs declarations from relocated export records ([lines 391–468](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/importer/ureader.go#L391-L468)). WW adopts those practical ownership and action semantics while retaining its small direct CLI representation and existing self-contained `.wwi` encoding. ### 11.13 Implemented unbounded semantic package-identity storage slice Canonical package identity is no longer stored in, derived from, or bounded by one internal filesystem component. In both drivers every package action now keeps these values separately: - `path`: the complete compiler/import identity; - `import_base`: the complete canonical ordinary directory identity; - `canon`: the complete canonical directory location; - `variant` and `role`: the semantic test/action tags; and - `storage`: an internal scratch basename that is never passed as package identity. `canon` participates in command-local directory-action interning, diagnostics, and storage-address derivation. The complete `path`, together with the semantic `variant` and `role`, is the persisted/compiler owner carried through source-import edges, module-reset and export ownership, compiler `--import` arguments, generated-main construction, and symbol qualification; `storage` participates in none of those identities. The reversible outside-root form is `__wwlocal.p` and is allocated to its exact length. It is neither truncated nor replaced by a digest, and `__wwlocal` remains unavailable to source imports. Package declarations classify package kind and contribute semantic export content; they do not validate a path leaf, supply a missing identity, or alter a command package's canonical path. Short actions retain their established `.unit.ww`, `.wwi`, `.s`, `.o`, and `.a` basenames when the basename plus `.unit.new` fits the 255-byte supported filesystem component bound and the complete path fits the host pathname API. An action that does not fit uses this bounded storage locator: ```text __wwpkg.v.r.h ``` The SHA-256 byte input is exactly: ```text "ww-package-storage-v2:" || ASCII( ":" ":") || complete semantic path || NUL || complete canonical directory ``` WW package paths and host paths cannot contain NUL, so that boundary is unambiguous. Variant and role are present in both the digest input and the visible locator tag. The digest is only an action-storage address: units still begin with `//ww:module-reset ` and may append deterministic driver-private resolution comments, while exports begin with `//ww:module `, compiler imports carry the complete path, and qualified declarations use it in generated symbols. A selected executable entry retains its intentional bare linker spelling. User-selected `-o` publication paths bypass this derivation completely. Storage assignment is command-global and finishes before any tool is invoked. If two actions prefer the same legacy basename, every unhashed member is readdressed through the complete-action formula instead of rejecting a valid package graph. If two already-addressed, unequal complete actions ever produce the same locator, both drivers issue the same full-identity storage-collision diagnostic before compilation. A persistent workdir also validates every existing regular `.unit.ww` voucher against the requested complete semantic owner before stale-tool invalidation or reuse; a missing voucher is cold state, while a malformed, non-regular, or wrong-owner voucher is a pre-tool error. Thus ordinary preferred-name collisions are resolved, and a digest collision cannot silently alias two live or warm package actions. That storage slice introduced build version 10 and test version 11 so an older flat-layout voucher was never accepted as current state. Section 11.16 records the current superseding formats. The persisted semantic owner is deliberately the complete canonical import path, not the canonical host directory: host location must not enter compiler artifacts. Variant and role are encoded in the locator itself. Canonical directory remains part of command-local action interning and the digest input, so distinct locations normally receive distinct slots. In the hypothetical case that two locations with the same import path, variant, and role also collide in SHA-256, they are still one semantic package identity: the freshly composed owner unit must byte-equal the committed unit before reuse, so different sources rebuild and identical sources produce the same deterministic artifacts. A digest collision between different semantic paths fails the existing complete-path owner check before tools. This preserves collision checking without serializing machine-specific canonical directories into units or exports and without a sidecar, registry, or new metadata protocol. The package coordinator derives no persistent container from a request directory or pattern. `-w DIR` names the driver's semantic-action store itself, and the driver independently derives every action locator in that store from the full semantic tuple above and validates each committed semantic owner. Equivalent direct, logical, relative, absolute, dotted, recursive, duplicate, and explicit-root-symlink requests that select the same canonical actions can therefore reuse the same slots; request shape cannot split or alias persistent state. For a delegated request only, a missing caller `-w` directory is created after graph, identity, visibility, cycle, closure, and output preflight. An explicit root symlink is followed and canonicalized; a source entry symlink to a regular file is followed under the entry name, a source-shaped symlink to a directory is ignored, and symlinked recursive children are not traversed. The old `SEP_IMPORT_PATH_MAX` and all corresponding 255-byte WWstage import, variant, local-identity, and generated-main checks are removed. Package names, canonical identities, reverse-resolved dotted identities, generated-main identities, compiler import paths, and Cstage assembler symbols now use exact allocations. Cstage's assembler no longer copies a line, operand, `TEXT`, or `DATA` symbol through 256-byte arrays, and the C checker no longer resolves a qualified type through a 128-byte prefix buffer. `PATH_MAX` remains only at actual host pathname and syscall boundaries; the 255-byte constant remains only as the conservative internal basename component bound. The former `SEP_MAXPKG`, `SEP_MAXPRODUCT`, and `SEP_MAXCONTEXT` action-count limits are removed by the dynamically sized package-universe implementation in the next section. The existing native observers exercise the new boundary with ordinary dotted identities over 255 bytes and punctuation-heavy reversible local identities over 255 bytes. They inspect the complete owner in units and exports, exact direct sorted/deduplicated `.wwi` compiler inputs, long mangled assembler symbols, complete archive-only link closures, runtime results, and independent Cstage/WWstage artifact bytes. Two deep outside-root directories declaring the same leaf coexist under distinct reversible identities. A long command package's internal, external, and one directory generated-main actions remain distinct while retaining its canonical package identity. Logical and literal roots, dependency-first and root-first discovery, equivalent and symlink spellings, reordered products, and warm requests reuse the same production action and persistent slot. The persistent diamond observer also changes a shared dependency export, proves rebuilding of its direct importers, and proves propagation stops when the regenerated export is byte-identical. This separation follows the pinned official Go 1.26.5 tag at commit `c19862e5f8415b4f24b189d065ed739517c548ba`, without adopting Go's cache, build IDs, importcfg, module machinery, or scheduler: - Source imports are expanded to canonical paths before being recorded ([`pkg.go`, lines 658–669](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L658-L669), [`pkg.go`, lines 1150–1178](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1150-L1178)). Local directories receive a deterministic pseudo-import identity derived from the full directory while directory and import path stay separate ([`pkg.go`, lines 633–647](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L633-L647), [`pkg.go`, lines 863–907](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L863-L907)). Resolution/package caches retain and reuse those complete values ([`pkg.go`, lines 833–842](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L833-L842), [`pkg.go`, lines 909–985](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L909-L985), [`pkg.go`, lines 1008–1029](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1008-L1029)). - `go/build` reverse-resolves directory ownership through ordered roots and performs the matching forward lookup while keeping directory, import path, declared name, and source lists separate ([`build.go`, lines 612–665](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L612-L665), [`build.go`, lines 725–767](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L725-L767), [`build.go`, lines 436–493](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L493)). - Go interns an action by operation and package pointer, returns an existing action for repeated compilation requests, and attaches only direct package dependencies ([`action.go`, lines 202–206](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L202-L206), [`action.go`, lines 437–447](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L447), [`action.go`, lines 628–658](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L658)). - Its `Action` keeps `Package`, `Objdir`, and `Target` as independent fields, then assigns a short `bNNN/` object directory unrelated to import identity ([`action.go`, lines 84–109](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L84-L109), [`action.go`, lines 383–394](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L383-L394)). Direct dependency identities map independently to archive paths, and the owner is compiled to fixed `_pkg_.a` ([`exec.go`, lines 864–884](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L864-L884), [`exec.go`, lines 928–935](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L928-L935), [`exec.go`, lines 1017–1033](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1017-L1033)). - Linking reuses the compiled root action and separately expands the complete reachable archive closure ([`action.go`, lines 919–957](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L919-L957), [`action.go`, lines 1034–1068](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L1034-L1068), [`exec.go`, lines 1592–1624](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1592-L1624), [`exec.go`, lines 1635–1647](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1635-L1647)). User `-o` separately controls the publication target ([`build.go`, lines 508–548](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L508-L548)). - Go's test loader models ordinary production, internal production-plus-test, external `_test`, and generated-main packages separately, reusing ordinary production when possible ([`test.go`, lines 85–102](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L85-L102), [`test.go`, lines 175–226](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L175-L226), [`test.go`, lines 228–293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L228-L293)). ### 11.14 Implemented dynamically sized command-global package universe Package, dependency, resolution-context, selected-product, traversal, support, order, and closure storage no longer has an arbitrary 256-element boundary. This is a storage correction, not a new build abstraction: source imports still form one command-global canonical package graph; each semantic package variant still has one action; each compiler still receives exactly its direct exports; and each executable linker still receives its complete reachable archive closure. The Cstage representation is exact and deliberately small: - `sepgraph.pkg` is a dynamically allocated `struct seppkg *` with logical count `n` and capacity `pkgcap`; - `sepgraph.context` is a dynamically allocated `struct sepcontext *` with logical count `ncontext` and capacity `contextcap`; - each `seppkg.deps` is a dynamically allocated `int *` with `ndeps` and `depcap`; - each `seppkg.context_state` is a lazily extended, zero-filled `unsigned char *` with `context_cap`; - each package owns a dynamically grown import-occurrence vector recording kind, source spelling, source file, line, column, and stable dependency action index; its separate dependency vector remains sorted/deduplicated; - parsed `sepproduct` values are a dynamically allocated vector, and each product stores its support-action index directly; and - package-load frames and topological-DFS frames are temporary dynamic vectors, replacing recursion proportional to graph depth. The WWstage representation is isomorphic. `sepgraph.pkg: []seppkg` and `sepgraph.context: []sepcontext` use allocated slice length as capacity and keep separate `n`/`ncontext` logical counts. Every `seppkg` owns a dynamically grown `bindings: []sepbind`, a dynamically grown `deps: []i32` with `ndeps`, and a lazily zero-extended `contextstate: []u8`. Products, load frames, and topological frames use typed dynamically allocated slices. `internal/wwpackage` continues to construct one union command for all selected directory-test groups, but now checks the complete `12 + 9*products + 2*includes` builder argument count before allocating or starting the driver. All graph and product growth starts at capacity 8 and doubles until it covers the requested element count. Cstage clamps before `INT_MAX`, checks the element count against `SIZE_MAX / sizeof(element)`, and publishes a `realloc` result only after success. WWstage checks against the same signed 32-bit count boundary, allocates a replacement typed slice, copies the live prefix, and publishes it only after success. Context-state growth copies old bytes and explicitly zeros the new tail. The shared deterministic failures are `ww: package graph is too large` for an unrepresentable count and `ww: out of memory` for failed storage; compiler and linker argument-count arithmetic is checked before allocation and before any affected tool invocation. Each driver records allocation/size failure during graph discovery and propagates it as a command-fatal load result, rather than treating it as one product's semantic failure and starting tools for a sibling root. The coordinator uses fallible dynamic storage for discovered paths, source/folder/group/plan vectors, process handles, tool environments, and complete builder/run argument vectors; it reports an oversized product set or allocation failure before the corresponding `exec.start` and cleans an already-created request temporary tree. Host pathname, filesystem-component, process-argument, and available-memory boundaries remain real host constraints; none is used as a disguised package-count maximum. Vector growth never changes semantic references. Dependency edges, resolution contexts, selected-product roots and variant roots, generated-main/support edges, load/topological frames, order entries, and closure membership are all stable `int`/`i32` indices. Code reserves a graph slot before taking an element pointer and never carries an element pointer across a graph reserve. Capacity, addresses, request order, product order, output names, and workdir location therefore cannot enter action identity, sorting, diagnostics, storage locators, or artifact bytes. Dependency lists retain byte-sorted insertion and duplicate elimination. The iterative loader retains mark-before-child and post-child command-import validation; the iterative tri-color DFS retains deterministic postorder and the complete live path for cycle diagnostics. No fixed package, product, context, action, support-map, traversal, order, or closure cardinality remains in either driver. The unrelated `SEP_MAXLFLAGS == 32` limit is retained solely for the existing `-L`/`-l` command-line interface; it neither indexes nor bounds package actions. Compiler and linker tools already allocate their import/input tables from `argc`; their genuine remaining process boundary is the host's executable-argument limit. The native package observers generate rather than commit large fixture trees. The extended `long_shared_link_closure_is_complete` builds and runs a chain of 300 ordinary directory packages under independent cold Cstage and WWstage work roots. Its command root directly imports all 300 packages and repeats one import, proving an action beyond index 256 compiles, the root receives exactly 300 sorted/deduplicated direct `.wwi` inputs, every ordinary action receives only its one direct export, every `.unit.ww` contains only its two byte-sorted owner sources, and the linker receives the root plus all 300 archives exactly once and no `.wwi`. A second command root imports only `p000`; it reuses all 300 ordinary actions and its exact linker line still contains the root followed by the full `p000` through `p299` transitive archive chain and runtime archive, proving that closure construction—not the wide root's direct imports—crosses the old boundary. The observer compares every unit, export, assembly, object, archive, and binary across stages. A second equivalent request against the same persistent store invokes no compiler or assembler. Changing `p257`'s export recompiles exactly `p257`, direct importer `p256`, and the wide root, and stops before `p255` after `p256` regenerates a byte-identical export. Closing the chain at `p299 -> p000` produces the complete stage-identical 300-node cycle diagnostic with empty compiler, assembler, and linker traces. `dynamic_package_universe_crosses_former_boundary` selects 257 canonical directory products in one direct request per stage. Fifty-two directories have combined same/external tests and each produces `ptest`, `pxtest`, and one directory `pmain`; 205 production-only directories take the no-test path. The shared support closure brings the command-global universe to exactly 370 compile actions and 422 assembler invocations, with 52 generated dispatchers, links, binaries, and results. The 205 no-test products have only ordinary production actions and statuses: no support-owned target, main, link, binary, or result. The observer reverses all directory descriptors between stages, proves one compile per action, runs a boundary combined binary, validates variant-owned units and external self substitution, and compares representative action artifacts, normalized traces, and binaries byte-for-byte. The same observer exercises the public `ww test /...` coordinator path against that persistent action store. The coordinator passes exactly 257 directory descriptors in one driver request, prints 52 combined `ok` reports and 205 no-test `?` reports, and performs no new compilation. An unchanged warm request again invokes no compiler or assembler; the 52 real products follow the existing explicit-output relink convention while no-test products still create no linker work. Existing focused observers continue to prove dependency-first/root-first canonical reuse, root-only/combined artifact identity, exact reordered-product trace bytes, and request-shape-independent persistent action reuse. This representation follows the semantic separation and scalable action construction in the pinned official Go 1.26.5 source, identified by [`VERSION`, lines 1–2](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/VERSION#L1-L2), at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - Go's loader states that repeated package lookup returns the same pointer ([`pkg.go`, lines 633–636](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L633-L636)), resolves canonical path and directory before package-data lookup ([lines 863–911](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L863-L911)), and reuses the package cached under the resolved `ImportPath` ([lines 757–768](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L757-L768)). - A Go builder has one command-global action cache, while each action's dependencies are a dynamically accumulated slice ([`action.go`, lines 38–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L38-L45), [lines 84–89](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L84-L89)). The cache key is operation plus canonical package pointer and returns the existing action ([lines 202–206](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L202-L206), [lines 437–447](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L447)). - Go constructs an archive compile action and dynamically appends actions only for the package's direct imports ([lines 628–659](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L659)). It separately interns a link action rooted in that cached compile action ([lines 919–958](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L919-L958)) and dynamically expands the complete transitive link closure ([lines 1034–1068](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L1034-L1068)). Requested package actions are likewise accumulated with `append` ([`build.go`, lines 519–534](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L519-L534), [lines 551–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L551-L558)). - During execution, Go builds one package from its own source list ([`exec.go`, lines 721–790](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L721-L790), [lines 928–935](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L928-L935)), maps its direct action dependencies into compiler inputs ([lines 864–884](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L864-L884)), and links the root archive with mappings for the complete link-action closure ([lines 1592–1647](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1592-L1647)). - `go/build` keeps directory, import identity, declared name, and ordinary, internal-test, and external-test file lists separate ([`build.go`, lines 436–493](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L493)); `ImportDir` explicitly processes the named directory ([lines 521–525](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L521-L525)), reads precisely that directory ([lines 859–900](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L859-L900)), and assigns accepted files to the separate package-owned lists ([lines 948–1039](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L948-L1039)). - Go's test loader explicitly returns generated main, internal production-plus- test, and external-test packages, reusing production when valid ([`test.go`, lines 85–102](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L85-L102)); constructs the internal, external, and generated-main variants separately ([lines 175–293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L175-L293)); dynamically appends, sorts, and deduplicates generated-main imports ([lines 315–376](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L315-L376)); and uses copy-on-write test variants while preserving unaffected package objects ([lines 421–474](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L421-L474)). WW adopts those package/action distinctions and scalable dependency accumulation, but not Go's build IDs, module system, importcfg, cache/CAS, preloader, parallel action scheduler, or network behavior. Normal local WW builds and tests remain offline, manifest-free, registry-free, database-free, CAS-free, and network-free. ### 11.15 Implemented internal-package import visibility A source import whose complete canonical import path contains a directory component named exactly `internal` is now contextual. Locate the final such component. Its parent directory is the ownership boundary, and the import is legal only when the importing source package's canonical filesystem directory is that boundary or a descendant at a real path-component boundary. Thus `domain.client` may import `domain.internal.secret`, while `outsider` and `domainx.client` may not. `internalx` has no special meaning. For `domain.internal.outer.internal.deep`, the final `internal` wins and the owner is `domain.internal.outer`, not `domain`. The complete dotted import identity determines whether the rule applies and how many components comprise the final `internal` plus its following suffix. WW removes those components from that source edge's resolved lexical target route, canonicalizes the resulting owner directory physically, and compares it with the already canonical physical importer directory. Stripping precedes physical canonicalization because a symlink at or below `internal` may point to a target with a different name or depth; an action spelling interned by an earlier edge is never reused for this contextual calculation. Cstage obtains directory canonicalization through `realpath`; WWstage uses its equivalent `chdir`/`getcwd` canonicalization. For explicit single-file compatibility roots, Cstage uses `realpath` and WWstage's component walker uses `lstat`/`readlink` plus the same canonical current-directory representation; both preserve component and trailing-directory semantics across symlinks. The equality-or-`/`-boundary comparison never uses a raw string prefix. This division is intentional: an unrelated physical ancestor literally named `internal` does not impose visibility on an import whose canonical identity has no such component, while a symlink spelling at or below an import-path `internal` cannot move the effective owner or importer. Explicit single-file compatibility roots use their canonicalized containing directory as the importer context. Directly selecting an internal directory as a command root remains legal because selection is not a source import. Visibility is an import-edge property, not part of canonical package or action identity. Both drivers resolve the complete target, intern or reuse its one canonical production action, and then perform the importer-context check before accepting the source binding or dependency edge. Consequently an allowed importer may load and compile the target normally, but that cached action cannot authorize a later forbidden importer. Reversing requested products or visiting the forbidden importer first produces the same result. No declared package name, leaf, output name, product ordinal, storage locator, hash, or test variant participates in the decision. Legal edges therefore retain the existing owner-only byte-sorted unit, exact sorted/deduplicated direct `.wwi` compiler inputs, deterministic archive, and complete archive-only linker closure. Cstage represents the rule with the bounded `sep_internal_parent_count`/`sep_internal_import_allowed` helpers in `cmd/ww/main.c`. WWstage has the isomorphic `sepinternalparentcount`/`sepinternalimportallowed` helpers in `selfhost/cmd/ww/main.ww`. Neither adds a package field, fixed-size package table, second action universe, or action-key input. A distinct `SEP_LOAD_INTERNAL` result propagates through the iterative loader. On rejection both stages emit the importing parser position followed by exactly: ```text use of internal package not allowed ``` The command returns immediately from graph loading, before directory-identity finalization, unit composition, workdir owner validation, stale-voucher invalidation, tool-identity recording, compiler, assembler, in-driver archive production, linker, publication, or execution. A cold rejection therefore commits no target/importer artifact or `.wwtool.*` state. A forbidden warm request cannot use a previously committed target to bypass the check and leaves the already committed target voucher and all tool records byte-unchanged. Allocation or path canonicalization failure remains a deterministic command-fatal pre-tool error; the visibility helper does not change stable package indices or growth behavior. Every selected source file reaches the same driver scan. The rule therefore applies to ordinary production sources, same-package test sources in the internal production-plus-test variant, external `_test` sources, and real source imports inside the test-support package. Generated-main-to-variant, generated-main-to-support, and coordinator product wiring remain synthetic edges and are not retroactively treated as source imports. No coordinator change is required: `cmd/wwtest` only dispatches, and `internal/wwpackage/package.ww` only discovers and classifies source groups, constructs the union request, and runs the driver; neither resolves a source import or owns its importing position. This follows only the pinned official Go 1.26.5 source at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `loadImport` resolves and reuses the canonical package first, then explicitly checks the rule on every import because the result depends on the importing code, and attaches the importing position ([`pkg.go`, lines 787–791](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L787-L791)). - The rule is the tree rooted at the parent of the target's `internal` directory ([`pkg.go`, lines 1463–1471](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1463-L1471)). A package named directly on the command line is not an import ([lines 1498–1502](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1498-L1502)), and the import-path boundary is located before filesystem containment ([lines 1505–1515](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1505-L1515)). - Go's filesystem branch cleans the importer and owner, requires a path-component-aware prefix, and retries with both paths symlink-expanded ([`pkg.go`, lines 1534–1546](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1534-L1546)). Its rejection text is exactly the diagnostic above ([lines 1564–1571](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1564-L1571)), and its exact-component search deliberately selects the final `internal` element as the most restrictive rule ([lines 1574–1590](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1574-L1590)). - Same-package and external test imports both pass through ordinary `loadImport` with their own source positions before variant construction ([`test.go`, lines 102–161](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L102-L161)). Generated test-main dependencies are synthesized separately ([lines 307–330](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L307-L330)). - Go's downstream action cache keys canonical package actions independently and consumes the already validated direct package imports, so visibility does not belong in action identity ([`action.go`, lines 437–455](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L455), [lines 628–657](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L657)). The focused native observer `internal_package_import_visibility` generates its lexical package/import tree under a temporary physical ancestor also named `internal`, while deliberate symlink destinations live outside that ancestor, so that unrelated-host-path case is exercised rather than documented only. It builds and runs allowed descendant, nested-final, `internalx`, and symlinked physical-owner cases; rejects outsider, sibling-prefix, nested-final, and symlink-escape cases at exact source positions with empty tool traces; maps an internal target symlinked to a differently shaped physical path back to its lexical owner's canonical directory; builds an internal package directly; and reverses requested allowed/forbidden product-descriptor order around one reused target. It checks ordinary, internal-test, and external-test source imports, generated-main transitive-export isolation, owner-only source order, direct export inputs, archive-only link closure, runtime results, warm no-op package production, rejection-state preservation, and the primary production chain's unit, export, assembly, object, archive, binary, and exact normalized tool arguments across independent cold Cstage and WWstage work roots. Test variants additionally compare their unit/export/archive bytes and exercise byte-equivalent runtime output in both stages. ### 11.16 Implemented manifest-free local vendor-directory imports The local package loader now expands only imports parsed from source. For a source package whose resolved lexical route is `/domain/app`, an import of `lib.math` probes these directory packages in order: ```text /domain/app/vendor/lib/math /domain/vendor/lib/math /vendor/lib/math ``` The walk stops at that edge's applicable active source root. It never walks an arbitrary filesystem ancestor and never acquires a boundary from another requested product. Each resolution context carries the current package's lexical route and source-root boundary. An explicitly identified root derives the boundary by removing and round-trip validating exactly its dotted identity components. An unbound literal root chooses the first precedence-valid strict ancestor in its own ordered search roots, or the selected directory itself. An ordinary child records the exact root that selected it; a vendored child inherits the parent's boundary. These values are contextual resolution state, not package/action identity. Before source scanning, a literal directory whose lexical route is representable below that boundary binds the complete relative dotted identity, including any `vendor` components. A truly rootless literal keeps its reversible `__wwlocal` identity and cannot be coalesced with a same-physical vendored action. Thus selecting a vendored directory directly remains legal without letting product order donate its action identity to or from a source import. A candidate shadows outer and ordinary candidates only when its directory contains an observed non-directory name ending in `.ww`. This deliberately includes `_test.ww` and the bare name `.ww`, matching Go's suffix probe; an actual subdirectory named `x.ww` and an unreadable candidate with no observed source do not shadow. Once a candidate is selected, normal package enumeration reports its real errors, including a test-only or otherwise production-empty directory, rather than falling through. Source retains only the effective spelling, such as `lib.math`. Selection assigns the target the complete expanded canonical identity, such as `domain.app.vendor.lib.math`, and separately canonicalizes its physical directory. The target's declared name independently supplies the default qualifier in each importing source file. The action key is that expanded identity and canonical directory, plus the existing variant/role. Different physical vendor copies are distinct; different expanded vendor routes remain distinct even when symlinks converge on one physical directory; repeated resolutions of the same pair reuse one action. Source spelling, importer context, product order, output name, declared leaf, and allocation/discovery order do not enter that key. The final exact non-terminal dotted component named `vendor` determines the effective suffix and owner. A nested path uses its final `vendor`; `vendorx` is ordinary; and a path ending exactly in `vendor` names an ordinary package. After resolution and action interning, every source edge first performs vendor visibility and then verifies source spelling. An allowed importer that directly spells an expanded path receives the source-position diagnostic: ```text must be imported as ``` An outside importer receives, with visibility taking diagnostic precedence: ```text use of vendored package not allowed ``` Directly selecting a directory below `vendor` remains legal because a command root is not a source import. Visibility derives the owner from the current edge's resolved lexical vendor route and only then canonicalizes that owner physically. It never strips components from the already-canonical target, whose symlink shape may have a different depth. The importer is its canonical physical directory. Equality or a real `/`-component descendant is allowed; a raw string prefix is not. Consequently an importer reached through a symlink is judged by its physical containment, while a vendor target symlinked to a differently shaped physical directory keeps the owner established by the lexical vendor route. The check runs after intern/reuse on every source edge, so an action loaded by an allowed importer cannot authorize a later forbidden spelling or importer. Cstage represents the resolution with `route` and `source_root` in `sepcontext`, the bounded `sep_resolve_source_import` and vendor helpers, stable integer action references in typed source bindings, and transient `{package,context}` loader children. WWstage uses the isomorphic `sepcontext`, `sepresolvesourceimport`, typed bindings, and transient child vector. The package-global dependency set remains the sorted/deduplicated canonical action set used for compilation and linking; contextual child traversal never creates a second universe or contaminates action identity. All new storage grows with checked allocation, and package/context vectors continue to expose only stable integer references across growth. A compile still receives one sorted, deduplicated `--import ` triple for each direct dependency. When source spelling differs, the driver additionally supplies the sorted, unique auxiliary mapping: ```text --import-map ``` Both compilers require the map target to be an existing direct `--import`, require source keys to be sorted and unique, and require a matching import in the primary source input. No leaf-equality condition exists. After parsing the primary input and before prepending imported interfaces, the compiler replaces its semantic import key while preserving source position and spelling. It then reads the expanded target's declared name from the direct `.wwi` and installs that name only in the declaring source file. Thus the map adds no dependency or export input, expanded identity flows into self-contained `.wwi` ownership and symbols, and direct exports still have no transitive leakage. Linking remains independent: each executable consumes its root archive and complete reachable archive closure, never `.wwi` or import-map inputs. Persistent units record resolution identity in ignored, deterministic comments: ```text //ww:vendor-dir //ww:import-map ``` Hex encoding keeps arbitrary legal filesystem bytes inside one comment. The metadata makes ordinary-to-vendor changes and vendor symlink retargeting invalidate the importer even when its source bytes and both already-warm export bytes happen to match. It contains no dependency body and does not alter source positions. The current workdir formats are build 15 and test 14. An equivalent warm request remains a package-production no-op; an export change propagates only through ordinary direct-export comparison. Production, same-package internal-test, external `_test`, and real source imports inside the test-support package all use this source-edge resolver. Generated-main-to-variant, generated-main-to-support, and coordinator product edges remain synthetic and receive no map or retroactive source legality. `cmd/wwtest` remains a dispatcher. `internal/wwpackage` still discovers and classifies source groups and submits one command-global union; it performs no vendor resolution. It creates only its removable command-temporary coordination tree. The private driver creates a missing delegated `-w` directory and a requested output directory only after all semantic graph and output preflight succeeds; a rejected request therefore leaves neither directory behind. Resolution, identity collision checks, contextual legality, dependency-failure propagation, cycles, command kind, publication paths, and action closures all finish before cold scratch acquisition, tool identity staging, producer execution, publication, or runtime execution. A request whose every product is already invalid returns without acquiring scratch. If a later producer or product fails, otherwise viable siblings may have been produced only into the same transaction; none is committed or executed. A forbidden or otherwise rejected warm request leaves committed vouchers, status files, tool records, and products byte-unchanged. This is only manifest-free local source-tree behavior. It does not implement Go modules, module vendor mode, `go.mod`, `vendor/modules.txt`, importcfg, build IDs, a package database, a CAS, registry access, or network lookup, and it is separate from the future locked vendor store in section 4.6. The rule follows the pinned official Go 1.26.5 source at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - source-derived imports are expanded and the expanded vendor path becomes the canonical import path ([`pkg.go`, lines 658–668](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L658-L668)); - resolution and canonical package-cache reuse occur before the contextual internal/vendor checks, which still run with the importing position on every source edge ([`pkg.go`, lines 722–796](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L722-L796)); - vendor lookup walks importer ancestors nearest-first to the applicable root, requires a source-bearing directory, and records the expanded identity ([`pkg.go`, lines 1213–1263](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1213-L1263)); - the source-bearing probe accepts any non-directory `.go` suffix and ignores directory-read failure ([`pkg.go`, lines 1418–1429](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1418-L1429)); - command roots remain legal, while an expanded source spelling must use its effective suffix ([`pkg.go`, lines 1593–1617](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1593-L1617)); - vendor ownership uses component-aware physical containment and symlink expansion ([`pkg.go`, lines 1620–1667](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1620-L1667)); - the final exact non-terminal `vendor` component controls the rule ([`pkg.go`, lines 1670–1688](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1670-L1688)); - production, internal-test, and external-test imports retain distinct raw source spellings/positions but each resolves canonically, while generated test-main wiring is synthetic ([`test.go`, lines 85–173](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L85-L173), [`test.go`, lines 175–266](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L175-L266), [`test.go`, lines 272–373](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L272-L373), [`go/build/build.go`, lines 415–493](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L415-L493)); and - action caching consumes the already-resolved package graph, while output publication remains a later concern ([`action.go`, lines 437–455](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L455), [`action.go`, lines 628–659](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L659), [`build.go`, lines 470–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L470-L558)). The native observer `vendor_directory_import_resolution` generates every source tree temporarily and runs both stages from independent cold work roots. It proves nearest/outer/root/ordinary selection and the active-root boundary; source-bearing versus empty candidates; distinct and reused actions, including same-physical symlink targets; exact spelling/visibility diagnostics and product-order reversal; final-component, terminal-name, component-prefix, and symlink behavior; direct vendored roots; production/internal/external/support source imports and synthetic-main isolation; owner-only sorted units, exact direct exports/import maps, archive-only link closures, runtime output, stage-equal normalized argv/artifacts/binaries, warm no-op production, and cold and warm rejection-state preservation. ### 11.17 Implemented manifest-free recursive local package-pattern selection Build and test now share one local request selector. A positional spelling with no `...` is one explicit directory root. In a spelling containing `...`, each occurrence in a valid UTF-8 spelling has Go's regular-expression wildcard semantics; an invalid UTF-8 pattern matches nothing, and a final `/...` also matches the directory before that suffix. WW applies the local matcher to its existing manifest-free `DIR/...` interface as well as `./...`, `../...`, and absolute spellings. It does not interpret the non-filesystem portion as a module or registry path. Multiple direct roots and patterns may be mixed in one command. For build, `--` before the first positional ends option parsing and every following argument is a package selector, including a spelling that begins with `-`. Once the first positional has already ended flag parsing, a later `--` is itself another package argument. Pattern expansion is request processing only. For each pattern, traversal starts at the directory prefix before the first `...` and is bounded to that physical tree. The selector never obtains a traversal or source-root boundary from another product. It produces canonical physical directory roots; only imports parsed from their real source files add dependency edges. The request spelling, wildcard prefix, match membership, output name, request order, and discovery order never become a package import identity or action key and never enter an import search path. The recursive eligibility rules are: - Directory entries are read completely and byte-sorted before processing. Every recursively encountered directory whose basename begins `.` or `_`, or equals `testdata`, is pruned with its subtree. An explicit literal selection bypasses these traversal exclusions, so those directories remain legal direct roots. - A directory owns only its immediate `.ww` directory entries. Basenames beginning `.` or `_` are ignored. As in `go/build`, a source symlink whose target is a regular file is read under the symlink entry's byte-sorted name; a source-shaped symlink to a directory is ignored. A subdirectory never donates sources to its parent. - A directory with at least one production or `*_test.ww` source is eligible. A recursively encountered source-empty directory is silently skipped. A direct source-empty root is an error. A malformed source-bearing directory is retained as a root and fails during ordinary package-clause or driver loading; malformed files in excluded or source-empty trees do not poison the request. - The traversal does not prune `vendor`. Instead a wildcard cannot consume a non-terminal exact path component named `vendor`. Thus `DIR/...` may select a code-bearing terminal `DIR/vendor` but not `DIR/vendor/x`. `DIR/vendor/...` explicitly selects that vendor root and its descendants until another non-terminal `vendor` becomes a barrier. `vendorx` is ordinary. The explicit traversal root is opened after following a directory symlink, as in Go. It may therefore name a target outside the lexical spelling, but the target becomes the canonical traversal boundary. Directory symlinks encountered below that root are never followed, so they cannot escape, create cycles, or change selection. A cyclic explicit root is rejected while canonicalizing it. Relative, absolute, dotted, and explicit-root-symlink spellings that reach one physical package collapse to one canonical root. This physical interning is WW's stronger command-global identity rule; it deliberately avoids Go's few GOPATH cases in which different lexical import paths can retain distinct package objects. Raw requested spellings are byte-sorted first and each is then lexically cleaned before traversal. Matched source paths are canonicalized, sorted by canonical directory and filename, and deduplicated. Products are then byte-sorted by canonical directory and variant. Duplicate patterns, overlapping patterns, and canonical aliases therefore select one root/product and reuse one action. Go itself processes patterns in argv order and suppresses later package objects; WW performs the stronger final canonical sort required by its request-order-independent command universe. Reversing request or product order does not change roots, diagnostics, normalized tool arguments, artifacts, or runtime output. An unmatched pattern emits: ```text ww: warning: "PATTERN" matched no packages ``` `PATTERN` is quoted with the pinned `strconv.Quote` rules, including deterministic escapes for quotes, backslashes, controls, non-printing Unicode, and malformed UTF-8 bytes. Warnings are emitted in the sorted request order. With no remaining roots, ordinary build without `-o` succeeds as an empty build, while test reports `ww test: no packages to test`. A build with a non-directory `-o` reports no packages to build; a directory `-o` reports no main packages to build. A non-directory `-o` still requires exactly one production root. An existing directory or spelling ending in `/` receives each selected command under its canonical directory basename; non-main selected roots receive no named output. Two commands with the same destination basename are rejected rather than overwriting one another. All selection, canonicalization, package-clause, duplicate-output, and unusable-request diagnostics precede producer execution. Raw `-o` and `-w` spellings and every derived directory-fan-out output, cold scratch name, persistent tool-record name, and package artifact are bounded and validated symmetrically before tools; a raw spelling that fits but whose suffix or command basename does not fit is rejected with the same Cstage/WWstage diagnostic and no filesystem publication. For a delegated multi-root or recursive `-S` build, `-w` is required so the assembly outputs have caller-owned persistent destinations instead of vanishing with the coordinator's temporary plan. Build and test begin with the same eligible canonical directory set. Recursive build removes a source-bearing root that has only test files; an explicitly selected test-only directory remains an unusable build root and fails. Build creates one production product per remaining directory. Test retains test-only directories and, after selection, constructs the already specified isolated production/no-test, internal production-plus-test, external `_test`, support, recompiled-for-test, and one directory-generated-main action. Pattern expansion does not create those actions; graph-owned substitution alone makes the augmented package visible through applicable external and transitive edges. Vendor selection remains distinct from vendor import resolution. Selecting a directory below `vendor`, literally or through an explicitly vendor-rooted pattern, keeps its complete canonical local identity; it is never shortened to the suffix after `vendor`, and its declaration never renames it. A generic recursive pattern does not expose vendored descendants as ordinary short command roots. Independently, an allowed real source import still searches nearest-first below local `vendor`, creates the expanded identity described in section 11.16, supplies the required `--import-map`, and performs spelling and visibility checks for that importer even when the canonical action already exists. The ownership split is exact: - `cmd/ww/main.c` and `selfhost/cmd/ww/main.ww` recognize recursive and multi-root build/test requests symmetrically and delegate them. Their private build route consumes production product descriptors in one command-global package universe. It records library-root completion without linking and links each command product independently. Recursive build forwards `-S`, `-L`, and `-l` through the same private product route; assembly-only products receive completion markers only after their producer pass succeeds. Both stages allocate the same bounded delegation argv and inherit the existing environment directly, so delegation adds no WWstage-only environment-copy allocation or failure point. - `internal/wwpackage/package.ww` owns pattern cleaning and matching, bounded directory traversal, source-bearing eligibility, canonical root/product sorting and deduplication, build-versus-test product classification, output coordination, and deterministic reporting. It does not resolve a source import and does not prepend a pattern root to `-I`. - `cmd/wwtest` remains a dispatcher. The Cstage and WWstage drivers own package enumeration, canonical identity, contextual import resolution, graph loading, variants, compilation, archive construction, linking, publication, and persistent reuse. Consequently the existing action and tool contracts remain unchanged after root selection. Every action unit contains only the owner's byte-sorted source files. A compiler receives exactly the sorted, deduplicated `.wwi` exports of direct source dependencies and any required vendor import-map binding. Each executable link receives its root archive and complete reachable archive closure, never a `.wwi`. Canonical duplicate roots reuse the same action; the pattern text, declared qualifier, and product receiving an output do not affect canonical or persistent action ownership. Selection and package-clause validation finish before the coordinator creates its removable temporary plan, and the coordinator never creates persistent state. Driver graph, identity, visibility, cycle, closure, and output validation finish before a missing delegated work or output directory is created and before scratch, voucher, status, tool-state, publication, or producer mutation. If later setup of another requested directory fails, both drivers remove every empty path prefix created by that setup while preserving all pre-existing caller directories. A cold rejected pattern leaves no partial request state. The same rejection against an existing caller work root leaves its marker and every committed artifact, voucher, and tool record byte-unchanged and invokes no producer. A valid equivalent direct or recursive warm request remains a package-production no-op; changed exports continue to propagate through direct dependencies only. This slice follows only official Go 1.26.5 source at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - local literal versus wildcard handling, the prefix before the first `...`, explicit root-symlink following, recursive exclusions, source-empty omission, and malformed-directory retention are in [`cmd/go/internal/search/search.go`, lines 276–418](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/search/search.go#L276-L418), and its quoted unmatched-pattern warning is at [lines 424–429](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/search/search.go#L424-L429); - wildcard syntax, the empty match for trailing `/...`, and the non-terminal `vendor` barrier are in [`cmd/internal/pkgpattern/pkgpattern.go`, lines 32–106](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/internal/pkgpattern/pkgpattern.go#L32-L106), including invalid-UTF-8 rejection at lines 75–76, with non-terminal vendor-element replacement implemented at [lines 125–137](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/internal/pkgpattern/pkgpattern.go#L125-L137); - manifest-free request expansion, canonical package loading, first-occurrence deduplication, and pattern membership are in [`cmd/go/internal/load/pkg.go`, lines 2922–2965](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2922-L2965), while source imports alone recurse through package loading at [lines 2024–2047](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2024-L2047); - build uses that common matcher, implements single versus directory `-o`, and omits wildcard-selected test-only roots at [`cmd/go/internal/work/build.go`, lines 459–559](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L559) and [lines 731–745](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L731-L745); - test uses the same package request set, reports an empty set, and constructs isolated test variants only afterward at [`cmd/go/internal/test/test.go`, lines 684–719](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L684-L719) and [lines 1133–1226](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1226); - immediate directory ownership and hidden/underscore source-name exclusion are in [`go/build/build.go`, lines 859–914](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L859-L914) (including regular-file source symlink following and symlink-to-directory omission at lines 886–900), parse-error retention and production/test classification are in [lines 931–1036](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L931-L1036), and `NoGoError` eligibility is in [lines 1076–1082](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1076-L1082); and - child symlinks are skipped by `Lstat`-based directory walking and entries are traversed in byte order at [`cmd/go/internal/fsys/walk.go`, lines 14–59](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/fsys/walk.go#L14-L59) and [`os/dir.go`, lines 109–125](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/dir.go#L109-L125). Build subcommand option termination is delegated by the Go command at [`cmd/go/main.go`, lines 312–321](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/main.go#L312-L321), with `--` termination implemented by [`flag/flag.go`, lines 1074–1089](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/flag/flag.go#L1074-L1089), and the parse loop stops at the first positional at [lines 1153–1176](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/flag/flag.go#L1153-L1176). Unmatched-pattern quoting uses the pinned `strconv.Quote` decoder and escape rules in [`strconv/quote.go`, lines 28–123](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/strconv/quote.go#L28-L123), including the exported `Quote` entry at lines 117–123, and the `IsPrint` algorithm at [`strconv/quote.go`, lines 515–559](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/strconv/quote.go#L515-L559), with its generated tables in [`strconv/isprint.go`, lines 8–733](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/strconv/isprint.go#L8-L733). No module cutoff, `go.mod`, module vendor mode, `vendor/modules.txt`, importcfg, build ID, registry, database, CAS, or network behavior is copied. The native observer `recursive_tree_discovery` generates every tree temporarily and runs Cstage and WWstage from independent cold roots. It covers ordinary and test-only roots, hidden/underscore/testdata exclusions and direct exceptions, terminal and explicit vendor patterns, an imported expanded vendor dependency at both package-local and ancestor vendor directories, overlapping/reversed/duplicate patterns independently in each stage, root, child-directory, regular-file, and directory-target source symlinks, canonical aliases, source-empty and malformed directories, build/test variant selection with an asserted common production-root set, middle-position and valid-UTF-8 wildcard edge cases, byte-sorted quoted unmatched diagnostics, multi-command directory output and duplicate-destination rejection, recursive assembly/link-flag forwarding, build `--` termination, raw-versus-derived output/scratch/work-path boundaries with zero producer calls, owner-only units, exact direct exports and import maps, archive-only links, normalized stage-equal tool argv and artifacts/binaries/output, warm no-op package production, and cold/warm pre-tool rejection-state preservation. The existing `vendor_directory_import_resolution` observer supplies the exact compiler `--import-map` argv proof for imported vendor dependencies, and the existing diamond and long-closure observers independently prove sorted/deduplicated direct `.wwi` cardinality and archive-only reachable link closures. ### 11.18 Implemented canonical identity, declared-name, and file-import-scope slice Directory-package identity and source naming are now independent throughout local build and test. For example: ```ww // canonical import identity: acme.codec package wire; ``` is imported with the existing dotted syntax: ```ww package main; import acme.codec; export fn main() i32 = { return wire.value(); }; ``` The package action, exports, symbols, archives, dependency edges, persistent storage ownership, and link closure remain owned by `acme.codec`. Only the source-file binding is named `wire`. The path leaf `codec` is not installed as another qualifier, and a sibling source file receives no `wire` binding unless that file has its own import. The implemented representation keeps six facts distinct: 1. source import spelling, including its source file, line, and column; 2. contextually expanded canonical import identity; 3. canonical physical directory; 4. the one declared package name read from eligible source clauses and `.wwi` package markers; 5. the optional explicit alias written at that import occurrence; and 6. the effective source-file-local qualifier, selected from the explicit alias when present and otherwise from the imported declaration. Both drivers retain one dynamically allocated `sepbind` occurrence for every real import site. The occurrence stores the source spelling and position plus a stable action index. Contextual `internal` and vendor resolution is therefore rechecked for every source import even if its target action already exists. A separate package dependency vector unions those occurrences, deduplicates by canonical action, and sorts by complete canonical identity/variant/role. That vector alone supplies dependency traversal and compiler `--import` arguments. Patterns, qualifiers, declared names, export closure facts, and generated edges never create source dependency edges. The owner-only composed unit preserves byte-sorted source boundaries with one `//ww:module-reset ` separator per file. Parser nodes carry a source-section ID as well as canonical owner and declared package name. Each real `N_USE` therefore belongs to one source section. `.wwi` emission repeats canonical-owner/package markers as needed for contributing source sections and retains imports only with the declarations from the file that owned them. Interfaces remain source-like transitional data, but canonical owner and declared name are no longer collapsed into one token. `w6c` and `w6c_ww` validate every direct export's leading canonical owner against its paired `--import` path. After all direct exports are parsed, they build canonical-path-to-declared-name metadata from those interfaces, apply any vendor `--import-map` only to canonical identity, and bind each primary source import through its explicit alias or, when absent, the imported declaration. The checkers and code generators select bindings by source-section ID and canonical owner. Only a qualified lookup through that effective binding marks the owning file's occurrence used; imported declarations are never a bare-name fallback. Two files may consequently bind the same name to different canonical packages, while the graph still contains one edge/action for each target. Within one file, two imports that produce the same effective qualifier are a redeclared binding; the later unused binding is also reported. An unused import is reported at its own import position even if a sibling file uses the same qualifier or canonical dependency. A package-scope declaration collides with an equal import binding from any contributing file, matching Go's reconciliation of package and file scopes. Conflicting production package clauses remain a loader-owned deterministic error before producers. Compiler-owned scope or use errors may invoke the compiler, but every action artifact remains staged under an adjacent `.new` name. No completion/status marker is written and no product is published after a failed compile. Once every action and product has staged, the driver preserves each existing destination under a request-owned backup, installs the complete new generation, and rolls all installed destinations back if any installation fails. Unit vouchers and the global stamp are transaction members rather than early invalidation markers. Thus a rejected or interrupted request leaves the previous committed generation byte-identical and removes all remaining stages; a mixed `.wwi`/object/archive generation is never reusable. Package kind follows the declaration. `package main`, not a path component, marks a command. A path ending in `main` remains importable when it declares a different name. Any ordinary source import of a package declared `main` is rejected as `package is a program, not an importable package`, regardless of its path leaf. The one pinned loader exception is an external test's exact same-directory import of the command production: it is rewired to the forced-library test copy. WW admits only that canonical colocated edge. Test naming is likewise declaration-based. Production and internal-test variants use the production declared name. When production files exist, external files must declare `_test`; a test-only directory may establish one consistent package name from its test files, as in pinned `go/build`. External action identity remains the canonical production identity plus the existing external variant suffix where that production exists. Imports found only in internal or external test files belong only to that action. Support and the directory generated-main retain isolated action identities and archive closures. A generated dispatcher privately binds its tested targets through repeated, byte-sorted `--test-target-package ` arguments so a command variant declared `main` does not collide with the dispatcher's own synthesized `main`; this is compiler-generated wiring distinct from ordinary source aliases. A real zero-test directory product marks all compiler-owned target/support metadata imports consumed. Those private bindings are installed or marked consumed only in the generated dispatcher's source section; an import from an earlier test-file section neither supplies nor satisfies it. Vendor expansion changes only canonical identity and physical selection. A source spelling such as `lib.codec` can resolve to `domain.app.vendor.lib.codec`, while the vendored package's declaration, for example `package wire`, supplies the default file-local qualifier. An explicit alias overrides only that qualifier. The driver emits one sorted semantic `--import-map lib.codec domain.app.vendor.lib.codec` and one direct export input despite repeated import occurrences in separate files. The expanded identity continues to own symbols, `.wwi`, archive, voucher, and link inputs. Canonical action interning remains the directory/path/variant model of sections 11.7 and 11.14. Independent file bindings never clone an action, and a declared name or source alias never enters an artifact basename or storage locator. Changing a dependency's declaration keeps the same action identity and causes each direct importer to be reconsidered. A default-bound importer may then fail because its old qualifier disappeared; an explicitly aliased importer keeps its binding, regenerates a canonical semantic export, and stops reverse propagation when those bytes are unchanged. An alias-only source edit rebuilds its owner but likewise leaves canonical export identity unchanged. An identical warm request remains a producer no-op. Build workdir format 15 and test format 14 prevent reuse of older vouchers that lack these semantics. Compiler argv still contains exactly the sorted, deduplicated `.wwi` exports of direct canonical dependencies; no transitive `.wwi` and no qualifier-derived path appears. Linker argv still contains only the executable root archive and complete reachable archive closure plus runtime/native inputs. Publication and completion occur only after the corresponding action/product succeeds. Responsibility is intentionally split as follows: - `internal/wwpackage` classifies production, internal, and external test files from their declarations, derives the allowed external name from the production declaration, expands request patterns, and submits variant roots. It does not resolve imports, choose qualifiers, or create dependency edges. - `cmd/ww/main.c` and `selfhost/cmd/ww/main.ww` own per-site parsing and contextual resolution, canonical directory/action interning, declared-name consistency, imported-command rejection, sorted dependency union, exact tool argv, variant/generated-main construction, persistence, linking, and publication. Their storage, diagnostics, call positions, and allocation failures are isomorphic. - `cmd/w6c`/`cmd/wcc` and `selfhost/cmd/w6c`/`selfhost/cmd/wcc` own export owner/name reading and writing, ordinary/aliased parse facts, file-local binding installation, collision and unused-import diagnostics, name/type lookup, canonical symbol ownership, and generated-dispatcher private qualification. Cstage and WWstage emit byte-identical applicable interfaces, assembly, archives, and binaries. - `cmd/wwtest` remains only the test-command dispatcher. The behavior follows pinned official Go 1.26.5 source at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `go/build.Package` stores `Dir`, `Name`, `ImportPath`, production files, and test files independently, while package-clause consistency is checked during file classification ([`go/build/build.go`, lines 436–493](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L493), [`go/build/build.go`, lines 939–1049](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L939-L1049)). - The loader interns by resolved `ImportPath`, keeps `ImportPath` and `Name` separate, constructs edges from source imports, and rejects an imported package whose `Name == "main"` except for the exact same-directory test case ([`cmd/go/internal/load/pkg.go`, lines 633–636](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L633-L636), [lines 757–806](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L757-L806), [lines 2024–2047](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2024-L2047)). - The test loader builds distinct production/internal/external/generated-main packages, derives external `Name` from `p.Name + "_test"`, handles the same-directory command self-import, and rewrites it to the library-form test copy ([`cmd/go/internal/load/test.go`, lines 144–203](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L144-L203), [lines 228–293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L228-L293), [lines 421–472](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L421-L472)). - `go/types.Package` stores independent path and name. The resolver creates one child scope per source file, uses the imported package's declared name when no alias is present, inserts imports into that file scope, reconciles them with package declarations, and reports unused imports ([`go/types/package.go`, lines 26–40](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/package.go#L26-L40), [`go/types/resolver.go`, lines 237–350](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L237-L350), [lines 463–480](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L463-L480), [lines 701–735](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L701-L735)). The production compiler mirrors those rules ([`cmd/compile/internal/types2/resolver.go`, lines 223–335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L223-L335), [lines 473–486](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L473-L486), [lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)). - Compiler export import reconstructs and interns package descriptors by canonical path while restoring their independently encoded package names and imports ([`cmd/compile/internal/importer/ureader.go`, lines 152–196](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/importer/ureader.go#L152-L196), [`go/internal/gcimporter/ureader.go`, lines 224–244](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/internal/gcimporter/ureader.go#L224-L244)). - Work actions consume cached canonical package objects and direct imports, while test execution builds and links the isolated test action graph ([`cmd/go/internal/work/action.go`, lines 437–455](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L455), [lines 628–659](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L659), [`cmd/go/internal/test/test.go`, lines 1133–1226](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1226)). Section 11.19 completes ordinary explicit aliases while retaining dotted, unquoted paths. Section 11.20 adds blank side-effect imports without adding a name. Grouped, quoted, and dot imports remain deliberately unimplemented. The focused native observer `declared_name_identity_and_file_import_scope` generates every tree temporarily and exercises both stages from independent cold roots. It proves the identity/name/qualifier split, file-local collision and unused behavior, one-edge/action reuse, command and imported-command rules, all test variants, vendor expansion, recursive/direct selection, owner-only units, exact direct exports and archive-only links, warm no-op behavior, declared-name invalidation, rejection-state preservation, normalized argv, artifact/binary identity, allocation-bearing runtime behavior, and request/product-order independence. ### 11.19 Implemented ordinary and explicitly aliased file-scoped imports WW now implements the two ordinary binding modes for its local dotted import model: ```ww import acme.codec; // effective qualifier is the declared package name import stable acme.codec; // effective qualifier is exactly stable ``` If canonical package `acme.codec` declares `package wire`, the first form exposes only `wire.Name`; the second exposes only `stable.Name`. Neither form also exposes `codec.Name`, the unused alternative qualifier, or bare `Name`. WW has no dot-import form, so an ordinary import never inserts the dependency's exported declarations into unqualified lookup. Builtins, lexical declarations, and same-package declarations retain ordinary bare lookup. This is the dotted-path counterpart of Go's independent local name and quoted path, without adopting quoted paths. The syntax AST stores the optional source alias independently from the original dotted spelling, canonical expanded identity, imported declared name, effective qualifier, owning source section, and source position. `Sym.use_alias` remains the older checker coexistence bit for a declaration that shares a leaf with a package qualifier; it is not the source-language alias fact. #### Pinned Go evidence The reference is official Go 1.26.5 source at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `go/ast.ImportSpec` stores `Name` and `Path` independently, and `Pos` selects the alias position when one exists ([`go/ast/ast.go`, lines 908–915 and 939–955](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/ast/ast.go#L908-L955)). `parseImportSpec` parses the optional local name separately from the path ([`go/parser/parser.go`, lines 2509–2546](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/parser/parser.go#L2509-L2546)). - `go/types` creates one child scope per source file, chooses an explicit alias when present and the imported package's declared name otherwise, inserts one ordinary package-name object, and inserts bare exports only for an explicit dot import ([`go/types/resolver.go`, lines 237–350](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L237-L350)). Package/file collisions and unused occurrences are handled at [`resolver.go`, lines 463–480](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L463-L480) and [`resolver.go`, lines 701–735](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L701-L735). The production compiler mirrors those rules at [`cmd/compile/internal/types2/resolver.go`, lines 223–335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L223-L335), [lines 472–489](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L472-L489), and [lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740). - Qualified selection marks the exact file-local package-name object used; bare imported declarations are associated only with the dot-import table ([`go/types/call.go`, lines 682–693](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/call.go#L682-L693), [`go/types/typexpr.go`, lines 20–31 and 79–86](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/typexpr.go#L20-L86)). Compiler diagnostics are stably sorted by source position before printing ([`cmd/compile/internal/base/print.go`, lines 70–92](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/base/print.go#L70-L92)). - Official testdata permits one path under distinct names, including default plus aliases, while keeping every occurrence independently subject to unused checking ([`internal/types/testdata/check/importdecl0/importdecl0a.go`, lines 29–52](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L29-L52), [`test/import.go`, lines 7–23](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/import.go#L7-L23), [`test/import1.go`, lines 7–18](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/import1.go#L7-L18)). - Canonical package path and declared name are independent in [`go/types/package.go`, lines 26–40](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/package.go#L26-L40). Unified export writes and restores canonical path and name independently ([`cmd/compile/internal/noder/writer.go`, lines 430–465](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/writer.go#L430-L465), [`cmd/compile/internal/importer/ureader.go`, lines 157–196](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/importer/ureader.go#L157-L196), [`cmd/compile/internal/noder/reader.go`, lines 342–376](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/reader.go#L342-L376)). - `go/build` keeps production, internal-test, and external-test files/imports separate and constructs their source import sets ([`go/build/build.go`, lines 436–505](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L505), [lines 939–1040](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L939-L1040), [lines 1061–1063](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1061-L1063)). `cmd/go` interns by canonical import path, performs internal/vendor checks at every real site, rejects imported `main`, and builds distinct test variants ([`cmd/go/internal/load/pkg.go`, lines 633–636](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L633-L636), [lines 757–806](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L757-L806), [lines 2024–2047](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2024-L2047), [`cmd/go/internal/load/test.go`, lines 175–293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L175-L293), [lines 421–484](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L421-L484)). - Build actions are keyed by operation and canonical package object, consume canonical direct dependencies, and link the reachable canonical closure ([`cmd/go/internal/work/action.go`, lines 202–206](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L202-L206), [lines 437–447](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L447), [lines 628–708](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L628-L708), [lines 919–968](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L919-L968), [lines 1034–1068](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L1034-L1068)). Root construction and test execution retain those canonical production and generated-test objects ([`cmd/go/internal/work/build.go`, lines 495–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L495-L558), [`cmd/go/internal/test/test.go`, lines 1133–1226 and 1297–1366](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1366)). Go's dot-import branch is negative evidence only: it demonstrates that bare foreign declarations require a distinct explicit mode. WW does not implement that mode. #### Scope, duplicate, collision, and usage rules Every import occurrence owns its spelling, optional alias, position, source section, and used bit. The effective qualifier is installed only in that section. A qualified type, value, function, def, const, or variable lookup maps the effective qualifier to canonical identity and marks that exact occurrence used. A failed bare lookup marks nothing. A sibling file cannot use or satisfy the occurrence, while two files may independently reuse one alias for different canonical packages. In one source file, equal effective qualifiers are duplicate bindings. The later occurrence remains independently unused; at one source position the duplicate diagnostic precedes its unused diagnostic. A later bare undefined name is printed after the earlier unused-import diagnostic. Equal canonical paths are otherwise not a conflict: distinct aliases, or default plus explicit alias, are accepted when their effective names differ and each occurrence is used. A package-scope declaration colliding with a file import is rejected in the existing deterministic reconciliation pass. The unused wording follows Go's leaf comparison: a binding equal to the path leaf says `imported and not used`; any other binding, including an unusual default declared name, says `imported as and not used`. `_` selects the no-binding side-effect mode completed in section 11.20. It is never an ordinary effective qualifier and therefore neither collides with another `_` occurrence nor receives an unused diagnostic. Grouped imports, quoted paths, and dot imports remain deliberately deferred. #### Graph, export, artifact, and persistence identity The imports-only parser and full parser share one import-spec routine and retain ordinary alias, blank mode, and dotted path separately. Both drivers sort and resolve occurrences by the dotted spelling, perform contextual internal and nearest-first vendor checks at every real site, and intern the expanded canonical action. `sepbind` and `--import-map` continue to mean source dotted spelling to expanded vendor identity; neither contains the alias or `_`. Repeated occurrences remain separate file facts but form one sorted canonical edge/action. The compiler independently reads the direct dependency's declared name. It installs the explicit alias when present or that declared name otherwise, while keeping the canonical owner on declarations, symbols, and code generation. A source alias cannot bypass imported-`main` rejection. Production, internal-test, external-test, support, and generated-main identities remain isolated, and an import found only in a test file reaches only its corresponding test variant. The coordinator remains responsible only for package/test classification and submitting those roots; it does not parse or rewrite imports. `.wwi` data never exports a local alias as package identity. Qualified exported type and constant references are normalized to a deterministic compiler-private qualifier `__wwi_` followed by the lowercase hexadecimal bytes of the canonical path. Matching import records still name the canonical path, and transitive fact sections carry the same canonical private spelling. The reader restores the real declared name from the direct owner's metadata while treating those private names as semantic placeholders. Thus two source aliases for the same canonical type produce the same interface bytes, even if two dependencies have the same declared name. The source/import and interface protocol change advances persistent build workdirs to format 15 and test workdirs to format 14. Older unit vouchers are invalidated before reuse, so an interface written with historical implicit-dot or declared-name spelling cannot preserve a stale qualifier under the new checker. Compiler argv remains exactly one sorted `--import ` pair per direct dependency plus the exact required vendor import maps. No transitive `.wwi` is passed. Symbols, objects, archives, vouchers, stamps, persistent directories, and product basenames remain canonical-action owned. Linker argv remains root plus reachable archives and native/runtime inputs only; it contains neither `.wwi` files nor alias-derived archive names. A dependency declared-name change invalidates its semantic export and reconsiders every direct importer. Default-bound unchanged source loses the old qualifier and is rejected cleanly. Explicitly aliased source stays valid; after its canonical interface regenerates unchanged, invalidation stops before unaffected reverse dependencies. An alias-only source edit rebuilds the edited owner but likewise cannot rename symbols or alter canonical export identity, so unchanged semantic bytes stop reverse rebuilding. Parser, identity, alias, declaration, binding, and scope failures occur before publication. Compiler-owned failures may start the compiler, but staged unit, interface, assembly, object, archive, voucher, stamp, status, and product state is discarded under section 11.20's request transaction. #### Stage and observer ownership The C and WW parsers retain identical alias/path/position facts. The Cstage and WWstage drivers resolve only the dotted path; the compiler mains restore the declared name and choose the effective binding; the checkers own duplicate, collision, usage, and file-scope lookup; the interface writers own canonical normalization; and code generators consume checker-stamped canonical types and module ownership. WWstage resolves all top-level function signatures in their declaring package before checking bodies, matching Cstage and preventing a consumer from reinterpreting a later declaration's bare same-package types. The native `explicit_import_alias_binding_modes` observer owns the focused ordinary/alias/bare-negative, duplicate, repeated-path, file-scope, canonical artifact, `.wwi`, and rejection-state matrix. The existing `declared_name_identity_and_file_import_scope` observer owns default-versus- stable-alias invalidation and propagation. Existing directory, command-test, vendor, recursive, exact-argv, link-closure, persistent-workdir, and request-transaction observers retain their broader variant and action ownership. Every applicable proof runs Cstage and WWstage from independent cold roots and compares diagnostics, normalized tool arguments, artifacts, binaries, and runtime output. ### 11.20 Implemented blank side-effect imports and package initialization WW now completes the third file-local import mode and the package initialization path needed to give it meaning: ```ww import acme.codec; // qualifier from the dependency declaration import stable acme.codec; // explicit file-local qualifier stable import _ acme.codec; // no qualifier; initialization side effect only ``` A blank occurrence retains its dotted source spelling, owning file, line, column, source section, and resolved canonical action, but creates no source binding and is exempt from unused-import checking. It exposes neither `wire.Name`, `codec.Name`, nor bare `Name`. Resolution always uses `acme.codec`, never `_`: missing-package, self-import, cycle, final-`internal`, nearest-first vendor, vendor-spelling, and imported-`main` checks run at every blank site exactly as they do for a named occurrence. A vendored blank import therefore keeps a source-to-expanded-identity `--import-map`; `_` enters no map, action key, task symbol, artifact, voucher, stamp, variant, or link input. Repeated blank imports of one path, in one file or several files, are valid. A blank occurrence may coexist with the default binding or any explicit alias of the same path. Every named occurrence remains independently subject to its ordinary duplicate-binding and usage rules. All occurrences survive in the owner unit and per-site validation data, while their package-wide union still forms one sorted canonical dependency edge, one package action, and one direct compiler export input. #### Pinned Go evidence The reference is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `ast.ImportSpec` keeps an optional local `Name`, including `_`, independent from `Path`, and the parser reads that optional name before the path ([`go/ast/ast.go`, lines 908–915 and 939–955](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/ast/ast.go#L908-L955), [`go/parser/parser.go`, lines 2509–2546](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/parser/parser.go#L2509-L2546)). Function parsing treats `init` as an ordinary syntactic function name; its special meaning is assigned later ([`go/parser/parser.go`, lines 2784–2842](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/parser/parser.go#L2784-L2842)). - `go/types` creates an import object for each occurrence, inserts no binding for `_`, exempts `_` from unused checking, and keeps a valid `init` function out of package scope while checking its body and signature ([`go/types/decl.go`, lines 16–33](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/decl.go#L16-L33), [`go/types/resolver.go`, lines 103–124](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L103-L124), [lines 279–350](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L279-L350), [lines 400–433](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L400-L433), [lines 701–716](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L701-L716)). The production compiler equivalent is [`cmd/compile/internal/types2/resolver.go`, lines 90–111](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L90-L111), [lines 264–335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L264-L335), [lines 416–444](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L416-L444) and [lines 706–721](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L721). - Official import testdata accepts repeated blanks and blank plus default or explicit named imports of the same path, while diagnosing only the unused named occurrences ([`internal/types/testdata/check/importdecl0/importdecl0a.go`, lines 9–31 and 43–52](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L9-L52)). Multiple valid init declarations, invalid signatures, and direct invisibility are pinned by [`test/init.go`, lines 12–18](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/init.go#L12-L18), [`test/noinit.go`, lines 315–326](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/noinit.go#L315-L326), [`internal/types/testdata/check/decls0.go`, lines 40–46](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/decls0.go#L40-L46), and [`decls1.go`, lines 141–146](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/decls1.go#L141-L146). - After constants, variable initialization chooses the declaration with the fewest unresolved variable dependencies and uses source order as its tie; references through functions are dependencies. Cycle reporting is deterministic, and graph removal continues so later independent cycles are also diagnosed ([`go/types/initorder.go`, lines 19–185 and 226–335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/initorder.go#L19-L335), [`cmd/compile/internal/types2/initorder.go`, lines 16–182 and 223–332](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/initorder.go#L16-L332)). Source ties and calls are exercised by [`go/types/api_test.go`, lines 1408–1619](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/api_test.go#L1408-L1619), with cycle ordering in [`internal/types/testdata/check/init0.go`, lines 22–89](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/init0.go#L22-L89). - The compiler first attempts static initialization and serializes remaining ordered assignments into a compiler-generated init function. It then emits one package task whose dependency tasks are separate `R_INITORDER` relocations and whose payload is an ordered function-pointer list ([`cmd/compile/internal/staticinit/sched.go`, lines 34–145](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/staticinit/sched.go#L34-L145), [`cmd/compile/internal/noder/writer.go`, lines 2717–2773](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/writer.go#L2717-L2773), [`cmd/compile/internal/noder/reader.go`, lines 3288–3345](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/reader.go#L3288-L3345), [lines 3389–3416](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/reader.go#L3389-L3416), [`cmd/compile/internal/pkginit/init.go`, lines 20–145](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/pkginit/init.go#L20-L145)). The requested historical `cmd/compile/internal/walk/init.go` path does not exist at this tag; the noder, `staticinit`, and `pkginit` files above are the active implementation. - The linker schedules ready tasks by canonical task symbol and emits each exactly once, and the runtime executes those tasks before user main ([`cmd/link/internal/ld/inittask.go`, lines 19–39 and 104–180](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/inittask.go#L19-L180), [`cmd/link/internal/ld/heap.go`, lines 56–99](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/heap.go#L56-L99), [`runtime/proc.go`, lines 203–290](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/runtime/proc.go#L203-L290), [lines 8049–8124](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/runtime/proc.go#L8049-L8124)). The `issue31636` packages exercise imports written out of order, while the linker queue above—not that fixture's stale comment—pins lexical ready-task order ([`test/fixedbugs/issue31636.dir/main.go`, lines 7–17](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/fixedbugs/issue31636.dir/main.go#L7-L17)). - `go/build` specifies sorted directory presentation; its default path obtains byte-sorted names and then classifies production, internal-test, and external-test files/imports separately ([`go/build/build.go`, lines 108–111 and 193–207](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L108-L207), [`os/dir.go`, lines 109–125](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/dir.go#L109-L125), [`go/build/build.go`, lines 948–1040](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L948-L1040), [lines 1061–1063](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1061-L1063), [lines 1512–1518](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1512-L1518)). The test loader constructs and rewrites canonical internal, external, and generated-main variants before work actions. In the internal variant it presents the already-sorted production category first and the already-sorted internal-test category second, rather than globally sorting the merge; its effective-test-cycle rule is pinned by [`cmd/go/internal/load/test.go`, lines 85–101, 175–293, and 421–550](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L85-L550) and [`cmd/go/testdata/script/list_test_cycle.txt`, lines 1–20](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/list_test_cycle.txt#L1-L20). Compile/link action ownership remains canonical in [`cmd/go/internal/work/action.go`, lines 437–455, 628–708, and 919–1068](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L437-L1068), while `go test` rejects a bad test graph before creating those actions ([`cmd/go/internal/test/test.go`, lines 1185–1226](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1185-L1226)). - Unified export data separates public objects from private bodies/init data; a blank import declaration serializes no declaration, and import readers consume the semantic package export independently of that local spelling ([`cmd/compile/internal/noder/unified.go`, lines 314–353](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/unified.go#L314-L353), [lines 463–570](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/unified.go#L463-L570), [`cmd/compile/internal/noder/writer.go`, lines 2742–2749](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/writer.go#L2742-L2749), [`cmd/compile/internal/importer/ureader.go`, lines 41–62](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/importer/ureader.go#L41-L62)). Together with the resolver's omission from package scope, that public/private split is why another package cannot select `pkg.init`. - Loader import checks, build-root action ownership, direct compiler import inputs, and transitive linker inputs remain per canonical package rather than per local import name ([`cmd/go/internal/load/pkg.go`, lines 787–805](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L787-L805), [`cmd/go/internal/work/build.go`, lines 519–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L519-L558), [`cmd/go/internal/work/exec.go`, lines 864–884](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L864-L884), [lines 1592–1653](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1592-L1653), [`cmd/go/internal/work/gc.go`, lines 136–177](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/gc.go#L136-L177), [lines 590–672](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/gc.go#L590-L672)). #### Declaration and package-variable semantics `fn init() void = { ... };` is a special initializer declaration. It must have a body, no parameters, no result, no `export`, and no attribute. Multiple valid declarations are accepted in one file and across files. No declaration of another kind may claim `init`; a rejected non-function form is not inserted into scope, so later references still fail lookup. A valid init retains its file, source section, and position, but is never installed as a callable declaration: `init()` and `pkg.init` fail lookup, it is absent from `.wwi`, and it cannot affect canonical package identity. Mutable package-level `let` is WW's Go-variable analogue. An initializer that the existing static-data emitter can represent remains static. Every other otherwise valid expression—including calls, allocation, and supported nested array, struct, tuple, and slice values—is evaluated once by a hidden package-owned helper and assigned to zero-backed package storage. Runtime slice literals use canonical writable backing storage rather than escaping a helper stack. `def` and `const` retain their existing compile-time/static rules and are not broadened by this implementation. The checker orders all initialized mutable lets by their checked declaration dependencies. References through package functions are transparent edges. Among remaining declarations, the one with the fewest unresolved dependencies wins and original declaration order breaks ties. Files arrive byte-sorted inside each loader category; a combined internal-test variant presents its production category before its internal-test category, and declarations retain source order inside each file. A cycle is reported on the same deterministic walk as the pinned type checkers; removal continues to expose later independent cycles, but any cycle suppresses all init lowering and publication. Runtime variable assignments execute in that order, then every special init function executes in owner-file/source order. Each semantic package action owns one hidden task symbol: ```text __ww..pkg.p..v.r.init ``` The reversible empty-owner form is likewise variant/role qualified. Neither a declared package name, default qualifier, explicit alias, blank spelling, path leaf, physical directory, request ordinal, nor output name contributes to this symbol. Compiler argv supplies it with `--package-init-symbol `. Only an executable command root or generated test main additionally receives `--init-dispatch-symbol __ww..dispatch`, and its compiler-generated entry calls that dispatcher before source `main` or the generated test main body. #### Product graph, variants, artifacts, and persistence Before any producer, the driver forms the effective reachable graph for each product, including internal-test replacement, and rejects a cycle introduced by that replacement. It repeatedly chooses the byte-lexically smallest ready canonical path, then variant and role, while blocking every importer on its dependencies. The resulting root-owned dispatcher calls each effective package task exactly once. Thus dependencies precede importers, a shared diamond task runs once per product, independent ties ignore source import order and linker argv order, and the root task completes before user main or tests. An ordinary library object/archive contains its hidden task but building the library does not execute it. An executable or generated-main root archive has two deterministic members, `pkg.o/` followed by `init.o/`; the second member is the root-owned dispatcher. Dependency archives remain ordinary `pkg.o/` archives. Both driver stages stream member bytes through the same bounded transfer buffer instead of retaining archive-sized allocations. Existing linker archive fixpoint extraction pulls the dispatcher and all referenced package tasks without a new linker format or free-floating artifact. Logical linker argv is still the canonical root archive followed by the reachable archive closure and runtime/native inputs; no `.wwi`, alias, blank spelling, or dispatcher sidecar appears. Production, production-plus-internal-test, external `_test`, test support, and directory generated main retain separate action identities. One canonical directory product replaces colocated production with `ptest` wherever internal tests augment it, rewires `pxtest` self-import and affected transitive importers to that action, and includes test-only blank edges/init declarations exactly once. Support is an ordinary dependency task; the one generated main owns only the final dispatcher call and cannot duplicate a tested task. Test-file-only imports, runtime lets, and init functions never enter production. A blank import cannot bypass imported-`main` rejection, including through vendor expansion. `.wwi` contains neither blank-only spelling, init declarations/bodies, hidden variable helpers, slice backing symbols, package tasks, nor dispatcher facts. It continues to encode only semantic exported declarations and their canonical reachable type/constant facts. Consequently an init-body-only edit rebuilds the owning object/archive and relinks affected products, while unchanged `.wwi` bytes prevent importer recompilation. Adding or removing a blank edge rebuilds the owning source action and changes exactly the affected reachable dispatcher; a dispatcher-only change rebuilds the root `init.o/` member/archive without recompiling an unchanged root source object. Reverse propagation stops at the first regenerated byte-identical semantic export. The owner source voucher remains `.unit.ww`; a linked product root also owns `.init.unit.ww` for its dispatcher unit, `.init.s`, `.init.o`, and two-member archive. Current persistent formats are build 18 and test 19. Warm consumers select a dependency's staged `.wwi.new` or `.a.new` when that exact action changed in the same request. All action artifacts, init artifacts, tool identity copies, stamp, library/executable publications, and test statuses are then one rollback-capable request transaction. No destination changes unless every product stages successfully; a compiler, checker, init-order, dispatcher, assembler, archiver, linker, allocation, status, or installation failure removes remaining stages and restores the complete prior generation. Before scratch acquisition or producer execution, `lstat`-style no-follow checks reserve every action, tool, product, interface, status, and rollback name; a dangling staging or backup symlink is an occupied structural conflict and is never followed or removed. A committed dispatcher voucher must itself be a regular file before it can authorize reuse. Compiler assembly and interface bytes are first generated through anonymous files with checked full writes and then published as their own rollback group. A non-regular compiler destination is rejected before preservation, except that an already existing character-device sink such as `/dev/null` receives a checked passthrough and is never renamed or treated as a persistent artifact. Installation—not cleanup of a recoverable old backup—is the commit point. Cold rejection removes the exact request-owned scratch tree. Stale init code, stale closure metadata, and mixed committed generations therefore cannot be reused. #### Stage and observer ownership The shared syntax AST, C parser, and WW parser own blank/init facts and source positions. Both imports-only driver scans resolve the dotted path and retain per-site legality; neither treats `_` as an alias. The C and WW checkers own special-init validation, invisibility, mutable-let dependency ordering, cycle diagnostics, and runtime lowering. The interface writers omit initialization implementation; the code generators emit static storage, runtime helpers, package tasks, canonical slice backings, and the entry dispatcher call. The two drivers own task identity, effective test graphs, global dispatcher ordering, exact direct compiler inputs, archive membership, link closure, persistence, and the request transaction. The assemblers consume the dynamically sized canonical symbols. Both linkers are unchanged and use their existing iterative archive extraction. `internal/wwpackage` and `cmd/wwtest` retain package/test classification and execution coordination; they do not parse imports, invent tasks, or call init manually. The focused native `test/sep/sepinit_test.ww` observer generates every source tree temporarily and proves runtime let/init order, dependency chains, diamonds, independent lexical ties, aggregate and allocation initialization, multiple-cycle diagnostics, special-init rejection, test-variant isolation, canonical task/dispatcher/archive bytes, init-only invalidation, and warm invalid-init rollback across independent Cstage and WWstage roots. Direct and recursive test legs compare the one directory dispatcher/archive and observable dependency, `ptest`, `pxtest`, then `pmain` order; every production and dependency task runs exactly once. Exact task counts include support and the single generated main. Rejection rows compare complete normalized diagnostics and prove cold scratch absence. The observer also uses a repository-built `setrlimit` launcher to find one shared bounded-memory ceiling at which both drivers fail before a producer, and proves no-follow atomic rejection of dangling driver staging and compiler rollback names, non-regular compiler destinations, and compiler output-write failures. The extended `explicit_import_alias_binding_modes` observer owns repeated blank/default/ alias/file-scope combinations and no-binding/unused behavior. Existing internal, vendor, imported-command, recursive, exact-argv, link-closure, persistent-workdir, rejection-state, byte-identity, and bootstrap observers own their unchanged broader boundaries. Grouped imports, quoted imports, and dot imports remain deliberately unimplemented. ### 11.21 Implemented Go platform filename eligibility Directory packages now apply Go 1.26.5's OS/architecture filename rule before a source can enter WW's production or test graph. This closes a loader-wide divergence rather than adding a syntax feature: WW remains a local, manifest-free toolchain with unquoted dotted imports and one supported target, `linux/amd64`. #### Pinned Go evidence and pre-fix divergence The reference is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `Context.matchFile` first rejects leading-dot/underscore names and unrelated extensions, calls `goodOSArchFile`, and only then joins and opens the source ([`go/build/build.go`, lines 1438–1509](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1438-L1509)). - `goodOSArchFile` cuts at the first dot, requires an underscore-prefixed suffix, removes a final `test` token, gives a known OS/architecture pair precedence over a final known single token, and treats every other suffix as ordinary ([`go/build/build.go`, lines 1980–2027](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1980-L2027)). Its match operation is against the selected `GOOS`/`GOARCH`, with only the documented Android/Linux, illumos/Solaris, and iOS/Darwin aliases ([`go/build/build.go`, lines 1933–1977](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1933-L1977)). - The exact past, present, and future filename-recognition sets are `syslist.KnownOS` and `syslist.KnownArch`; they are intentionally broader than currently supported targets and explicitly must not lose old names ([`internal/syslist/syslist.go`, lines 14–36 and 56–83](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/syslist/syslist.go#L14-L83)). - `go/build` requires sorted directory presentation, its ordinary reader uses byte-sorted names, and package classification consumes that order ([`go/build/build.go`, lines 108–111 and 193–207](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L108-L207), [lines 859–914](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L859-L914), [`os/dir.go`, lines 109–125](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/dir.go#L109-L125)). - The official `TestMatchFile` table accepts `android.go`, `plan9.go`, and `plan9_test.go` as whole-name ordinary files, accepts matching architecture and Android/Linux aliases, and rejects a mismatching `foo_darwin.go` ([`go/build/build_test.go`, lines 381–425](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L381-L425)). Command testdata independently proves that a selected Linux suffix contributes its file and import on `linux/amd64` and both disappear on Darwin ([`cmd/go/testdata/script/list_constraints.txt`, lines 1–29 and 57–60](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/list_constraints.txt#L1-L60)). An explicit package whose files are all excluded is rejected ([`build_no_go.txt`, lines 1–17 and 31–41](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_no_go.txt#L1-L41)). Before this slice, both drivers accepted every visible `.ww` entry apart from the production/test partition, and `internal/wwpackage` discovered every such entry recursively. They opened and parsed candidates in raw filesystem order. On Linux/amd64, a malformed `bad_windows.ww` therefore rejected the request; an otherwise valid `platform_windows_arm64.ww` could add imports, actions, direct `.wwi` inputs, archives, linker inputs, initialization, and runtime behavior; wrong-target internal and external tests ran; a directory containing only `only_windows.ww` was selected recursively; and editing an ineligible file recompiled its owner. Cstage and WWstage agreed with each other but were both wrong. #### Final source and graph ownership The basename predicate is exact and allocation-free. It examines the stem before the first dot, removes final `_test` for suffix analysis, then recognizes only the pinned Go `KnownOS`/`KnownArch` sets. A recognized pair must be `linux_amd64`; a recognized final single must be `linux` or `amd64`. Unknown or misplaced tokens remain ordinary. There is no alias-, declared-name-, path-leaf-, physical-directory-, artifact-, or request-order input to this decision. Both drivers first collect every visible `.ww` basename in checked dynamically grown storage, byte-sort the names, then apply target and production/test eligibility before source stat/open/parse and package validation. This removes the former filesystem-order diagnostic race and adds no fixed file bound. The shared coordinator already sorts directory entries; its source predicate now removes a mismatching basename before it is appended to discovery or grouped into a package/test product. A recursive pattern skips a directory with no eligible sources. An explicit directory with no eligible production source retains WW's stable `directory contains no WW package sources` rejection. Eligibility owns whether a source occurrence exists. For a selected file, the parser and checker retain its exact file-local imports, aliases, blank occurrences, positions, and declarations, and the package graph deduplicates their resolved canonical targets exactly as before. For an excluded file there is no occurrence to resolve: missing, self, cycle, final-`internal`, vendor, and imported-`main` validation do not run, and the file contributes no canonical dependency or action. This is source/file ownership before package-graph ownership, never another identity dimension. #### Build, test, artifacts, and execution Production sees all matching non-test sources. The internal-test variant sees that production category followed by matching same-package `*_test.ww` files; the external variant sees only matching external `*_test.ww` files. The suffix rule therefore removes wrong-target test-only imports and initialization before variant construction, support generation, or generated-main generation. `plan9_test.ww` remains ordinary because the suffix has no nonempty prefix; `x_plan9_test.ww` is excluded; first-dot and pair-precedence cases behave like the pinned Go table. No checker, interface writer, assembler, archiver, or linker protocol changed. The drivers simply stop excluded bytes before those owners. Each selected package unit still contains its category-ordered source files and exact import occurrences. The compiler still receives one byte-sorted direct `.wwi` input per canonical edge; `.wwi` still contains only semantic exports; archives still contain only their canonical package action (plus the command root dispatcher member where applicable); and the linker still receives the root plus reachable archive-only closure. An import found only in an excluded file therefore creates no `.wwi`, object, archive, init task, dispatcher edge, linker argument, binary effect, or test execution. #### Persistence, rejection, and stage responsibility Persistent formats are build 18 and test 19 so a pre-slice workdir performs one complete reachable-action refresh under the new membership contract. Thereafter an excluded-file add, removal, or content edit changes no unit voucher, `.wwi`, assembly, object, archive, dispatcher, test status, or reverse action. Existing product policy may still relink an explicitly requested executable from its unchanged archives. A selected private implementation edit rebuilds its owner; if its `.wwi` is byte-identical, reverse compilation stops and only affected products relink. Wrong-target malformed sources and wrong-target structural import sites are ignored without producers. Selected structural failures are reported in byte-sorted filename order before producers. Any later selected-source compiler failure remains inside the existing request transaction: staged dependency changes are discarded, all prior actions/tool records/stamps/publications stay byte-identical, no `.new` generation survives, and no mixed package or test result is published. `cmd/ww/main.c` and `selfhost/cmd/ww/main.ww` mechanically mirror direct enumeration, sorting, target filtering, and checked allocation. The shared `internal/wwpackage/package.ww` predicate owns recursive build/test discovery. The compiler/checker/writer consume only selected units and require no special case; `w6a` and `w6l` remain unchanged. The focused native `platform_filename_source_selection` observer generates independent cold and persistent Cstage/WWstage work roots and proves exact suffix edge cases, sorted diagnostics, direct and recursive build/test selection, production/test isolation, repeated-edge canonicalization, exact compiler/assembler/linker argv, archive-only closure, artifact/assembly/binary equality, reversed-root independence, runtime results, ignored-edit reuse, `.wwi`-stable reverse propagation, and late-failure rollback. Existing dynamic-allocation, no-follow, byte-identity, bootstrap, internal, vendor, and imported-command observers retain their broader ownership. Source-level `//go:build`/`+build` equivalents, arbitrary tags, cross-target selection, grouped/quoted/dot imports, modules, manifests, registries, and a programmable build language remain deliberately unsupported. Go's `UseAllFiles` escape is also not exposed. Section 11.22 closes the formerly separate directory test-product topology divergence without changing these filename eligibility boundaries. ### 11.22 Implemented one canonical directory package-test product `ww test` now owns one practical test product per canonical selected directory, not one product per declared test package. Production, augmented internal test, external test, support, recompiled dependency, and generated-main actions stay separate compilation units; only their execution/publication ownership is unified. This is the applicable Go 1.26.5 topology for WW's local, dotted, manifest-free package model. #### Pinned Go evidence and pre-fix divergence The reference is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `TestPackagesFor` defines one `pmain` test binary running `ptest` and optional `pxtest`, with `ptest` equal to production plus same-package test files ([`cmd/go/internal/load/test.go`, lines 85–101 and 175–226](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L85-L101)). - External self-import is recognized before the external package is formed and is rebound to `ptest`, not ordinary `p` ([lines 144–161 and 228–266](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L144-L161)). - One `pmain` receives both applicable targets, one sorted import set, and then `recompileForTest` copy-on-write rewires every affected transitive importer from ordinary production to the augmented package ([lines 272–293, 342–376, and 421–490](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L272-L293)). - The generated source scans both target classes into one function set and one `testing.MainStart`/`Run` ([lines 595–638 and 790–860](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L595-L638)). - A directory with no selected test files takes the early ordinary-production compile path and creates no test support, generated main, link, executable, or subprocess; its print action reports `[no test files]` ([`cmd/go/internal/test/test.go`, lines 1133–1170 and 1524–1557](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1170)). - A real test package creates one generated source, one link action, and one output-copy/install or run action, including `-c`/`-o` ([lines 1200–1364](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1200-L1364)). - Go's action cache distinguishes cloned package objects even when their import paths match, compiler inputs come from the selected action's direct dependencies, and the link closure selects one archive per import path ([`cmd/go/internal/work/action.go`, lines 202–206, 437–447, and 628–658](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L202-L206), [`exec.go`, lines 410–438 and 864–884](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L410-L438)). - `go/build` classifies same-package and `_test` external files independently and accepts directories containing only either class ([`go/build/build.go`, lines 948–953, 1005–1036, and 1076–1082](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L948-L953)). Official command testdata closes the observable cases. `test_empty.txt` lines 3–24 and 30–53 accepts production-only, internal-only, external-only, combined, test-only internal, test-only external, and mixed test-only directories ([source](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_empty.txt#L3-L24)). `vendor_test_issue11864.txt` lines 8–9 and 64–80 proves an external test can use an export declared only in an internal test source ([source](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/vendor_test_issue11864.txt#L64-L80)). `list_test_imports.txt` lines 3–21 proves transitive rebuilding when a helper imports the package under test ([source](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/list_test_imports.txt#L3-L21)). `toolexec.txt` lines 27–50 observes distinct `ptest`, `pxtest`, and `pmain` compiles but one main and linker call ([source](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/toolexec.txt#L27-L50)). `test_no_tests.txt` lines 1–14 uses a panicking production initializer to prove that no-test reporting does not execute a test process ([source](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_no_tests.txt#L1-L14)). Before this slice WW constructed one generated main, link, binary, result, and report for each declared same/external test package. A combined directory ran two processes, initialized production state twice, hid internal-test exports from the external package, and made `-c -o` fail as a multi-product request. Even a directory with no selected tests manufactured support, a main, a link, and a temporary executable merely to print `[no tests]`. Test-only external directories were mislabeled, a valid mixed test-only directory was rejected, and a transitive importer was compiled against ordinary production. #### Final product and action topology For canonical directory product `P`, the action graph is: - `p`: ordinary production sources only; - `ptest`: production plus same-package selected `*_test.ww` sources; - `pxtest`: external-package selected `*_test.ww` sources only; - product-scoped recompiled actions: unchanged source units whose direct target set was rewritten by the `p -> ptest` substitution; - support: one command-global production support action (or the reserved `__wwtest` compiler binding when user `test` occupies that spelling); - `pmain`: one directory-owned generated-main action importing every applicable target and support. The source shapes produce these reachable roots: | Directory shape | Test closure and externally visible product | | --- | --- | | production, no selected tests | ordinary `p`; no support/main/link/run/output/result | | production + internal | `ptest` + `pmain`; one binary/result | | production + external | unaugmented `p` + `pxtest` + `pmain`; one binary/result | | production + both | `ptest` + `pxtest -> ptest` + `pmain`; one binary/result | | test-only same package | `ptest` + `pmain`; one binary/result | | test-only external package | `pxtest` + `pmain`; one binary/result | | test-only same + external | `ptest` + `pxtest -> ptest` + `pmain`; one binary/result | A selected helper-only `*_test.ww` file is still a real test source: it is loaded and may yield an empty harness. The no-real-run branch is specifically the absence of selected test files after platform filtering. Ordinary `ww build` excludes test filenames before reading even their package clauses, so malformed test-only content and test-only imports cannot affect production. The coordinator in `internal/wwpackage/package.ww` classifies all selected files into one directory group. Classification is production-name-relative, so a legitimate production package literally named `foo_test` has external name `foo_test_test`; without production, a valid `p`/`p_test` pair is retained as same/external rather than blindly stripping every suffix. The private driver descriptor is an ordered directory record: ``` --ww-package-test KIND FAMILY PRODUCTION INTERNAL EXTERNAL DIR OUTPUT PUBLICATION STATUS ``` Missing action selectors and absent publication are `-`. `OUTPUT` is the request-private runnable, while optional `PUBLICATION` is its caller-visible retained copy. One descriptor owns at most one output, publication, and status. Canonically duplicate products and pairwise output/publication/status/staging collisions reject before producer execution. Declared names and output stems do not identify products or actions. The Cstage and WWstage drivers first load and validate the ordinary production root. They form `ptest` and `pxtest` as separate source actions, bind external self-import to `ptest`, seed `p -> ptest`, and copy/rewrite the affected dependency closure. Both deduplicated dependency edges and every original file-local import binding target are rewritten through action identity. The strict closure validator rejects any leaked ordinary/augmented duplicate; no initialization or archive-order fallback can hide an incomplete substitution. `pmain` stores a checked, byte-sorted unique target action set. Its generated unit imports each target once plus support. The compiler argv repeats `--test-target-package` in that same order, followed by the exact byte-sorted direct `--import PATH WWI` set. Thus a combined shape has the essential form: ``` w6c --test-package ... -I PTEST.wwi -o PTEST.s PTEST.unit.ww w6c --test-package ... --import P PTEST.wwi ... -I PXTEST.wwi ... w6c -T --entry --test-support-module test \ --test-target-package P --test-target-package P_test \ --import P PTEST.wwi --import P_test PXTEST.wwi --import test TEST.wwi \ -I PMAIN.wwi -o PMAIN.s PMAIN.unit.ww ``` Actual arguments also contain action-owned init and dispatcher symbols. The assembler receives one source object per compiled action and exactly one `pmain.init.s -> pmain.init.o` dispatcher. Test target archives contain only their deterministic `pkg.o` member; the main archive contains `pkg.o` then `init.o`. Link argv is root plus reachable archives only: ``` w6l -o OUTPUT.new PMAIN.a [PXTEST.a] [PTEST-or-P.a] ... TEST.a libwwrt.a ``` No `.wwi`, source filename, standalone semantic object, or linker-order choice participates. Both native linkers already resolve archive members by symbols; they required no topology-specific change. #### Import, export, initialization, and execution ownership Default, explicit-alias, and blank imports remain file-local source occurrences. The package graph still uses one canonical edge per target and preserves every occurrence for usage and legality diagnostics. Substitution changes only the chosen canonical action. Consequently an external source continues to spell `import P`, but its direct compiler export input is `ptest.wwi`; an exported helper in an internal test source is ordinary augmented package export data and needs no special reader format. Per-owner `@test` metadata in `.wwi` remains sufficient. The writer/reader format did not change. `cmd/w6c/main.c`, `cmd/wcc/ww.h`, and `cmd/wcc/check.c`, with their self-hosted twins, changed singular generated-target state into a target set. Every target import is marked used, and every imported `@test` declaration receives its canonical target qualifier. The coordinator controls target order; the checker does not resolve directories. `wwdump` passes an empty target set on its non-test path. One dependency-first dispatcher is generated from the substituted closure. Each reachable canonical action contributes one initialization task; `pmain` is the sole entry package that calls the dispatcher. A combined directory therefore initializes dependencies, augmented production, external tests, support, and main exactly once in one process. Filtering and listing operate on the single deterministic enumeration containing both target sets; output has one accounting block and one directory report. `ww test -c -o OUTPUT DIR` publishes the one directory binary even when both target classes exist. #### Artifacts, persistence, invalidation, and rejection Semantic action artifacts remain separate: `.unit.ww`, `.wwi`, `.s`, `.o`, and `.a` for each production/test/recompiled/main/support action, plus main init unit/assembly/object. The directory product alone owns the binary, status, and result. Test persistent-work format is `19`; semantic package storage is format `3` and includes the product-scoped `for_test` identity for recompiled actions. There is still no cache, CAS, manifest, registry, database, or result cache. Warm reuse compares owner-unit bytes and exact direct export bytes. An internal helper body edit with stable `.wwi` rebuilds only `ptest` and relinks; external and reverse compilation stop. An external body-only edit rebuilds only `pxtest`. Adding or changing an exported internal helper changes `ptest.wwi`, then rebuilds exactly affected recompiled importers, `pxtest`, and `pmain`. Adding or removing a target class changes only the owning directory product and newly reachable actions. Request/root order and equivalent directory spelling do not change action bytes, target order, output, or reuse. Loader-owned source classification, import legality, canonical-product, duplicate-closure, cycle, command-kind, and publication-path errors reject before compiler, assembler, linker, support, or main work. Production failure is diagnosed once even though an augmented action would contain the same sources. Later compiler, assembler, generated-main, archive, link, staging, or commit failure remains one request-wide transaction: no sibling product runs, no status/result/binary or mixed generation is published, prior committed bytes remain unchanged, and every staged `.new` is discarded. Both drivers use checked dynamic allocation and transactional clone construction; allocation failure cannot publish a partial action or leave cleanup to traverse uninitialized storage. The native proof is primarily `directory_package_graph_variants`, `multi_directory_shared_package_plan`, `empty_and_invalid_package_classes`, `dynamic_package_universe_crosses_former_boundary`, `platform_filename_source_selection`, `vendor_directory_import_resolution`, and `test_variant_initialization`, with late transaction ownership in `sibling_test_variant_failures_are_isolated`. Together they compare cold/persistent Cstage and WWstage units, exports, assembly, objects, exact archive members, mains, binaries, diagnostics, runtime order, literal and normalized compiler/assembler/linker argv, both root orders in each stage, precise body/export and target-removal/re-addition invalidation, combined-graph allocation failure, repeated late internal/external/main/link rollback, and a complete work-directory sweep for staged residue. At completion of this earlier topology slice, deliberately unchanged or unsupported behavior included the raw single-file compatibility path, the then-current `[no tests]` presentation text, Go modules and build cache, network resolution, manifests, coverage/vet/fuzz/benchmark generation, source-level build expressions, quoted/grouped/dot imports, and targets other than the separately specified fixed `linux/amd64` filename selection. Section 11.35 subsequently closes only that presentation-text gap. None is used to define canonical package or directory-product identity. ### 11.23 Implemented case-fold collision preflight This slice pins the collision semantics to Go 1.26.5, tag commit `c19862e5f8415b4f24b189d065ed739517c548ba`. The official command loader uses an exact import cache at `src/cmd/go/internal/load/pkg.go:633-636,757-775`, performs contextual and vendor resolution before cache lookup at `:840-911,974-1005`, owns one command-global folded import table at `:1725`, and rejects a second fold-equivalent import spelling at `:1950-1959`. Its selected-name collision is over `Package.AllFiles` (`:149-194`) and is applied at `:1991-2000`. `src/cmd/go/internal/str/str.go:32-89` defines the pinned `ToFold` and `FoldDup` algorithms; the direct, transitive, and filename expectations are in `src/cmd/go/testdata/script/list_case_collision.txt:1-41`. Filename discovery and package/test classification are ordered by `src/go/build/build.go:859-914,1005-1036,1076-1082,1450-1469`. Before this slice, a Linux case-sensitive filesystem let distinct directories such as `domain.Foo` and `domain.foo`, expanded vendor identities, and selected files such as `File.ww` and `file.ww` build as unrelated packages or sources. Both Cstage and WWstage did so byte-identically. A symlink making the two import spellings reach one directory happened to trip the older exact directory/identity check, but that host-physical consequence was neither the Go diagnostic nor the required package-graph rule. #### Exact identity and request-only folded keys Canonical package identity remains the exact, case-sensitive effective dotted identity. It is still the key used by action interning, source import maps, `.wwi` ownership, mangled symbols, storage digests, archives, diagnostics, and link closure. Default bindings, explicit aliases, blank imports, declared package names, path leaves, artifacts, and physical directories do not replace it. Exact repeated occurrences therefore continue to form one canonical edge and one package action. The loader graph additionally owns a checked, dynamically grown, request-only table from a simple-fold key to the first exact package representative. Every ordinary effective identity registers after contextual local/vendor expansion and before exact action reuse or physical-directory conflict checks. Exact reuse succeeds. A distinct spelling with the same key rejects as `ww: case-insensitive import collision: "A" and "a"`; WW byte-sorts the two exact spellings so root, request, import, and discovery order cannot select a different diagnostic. It never stores, interns, looks up, or publishes the folded spelling as package identity. WW dotted import components are ASCII by construction: the C lexer/parser accept them through `cmd/wcc/lex.c:53-63` and `cmd/wcc/parse.c:1318-1353`, and the self-hosted syntax path mirrors that in `lib/ww/syntax/lex.ww` and `lib/ww/syntax/decl.ww`. Context-derived identities are revalidated, and arbitrary local filesystem bytes are escaped into ASCII. The general Unicode fold routine is nevertheless shared with filename preflight; for package identities its observable domain reduces exactly to ASCII case folding. Vendor imports register the fully expanded canonical identity, not the short source spelling. Thus `lib.Foo` and `lib.foo` reached below one vendor owner collide as, for example, `domain.app.vendor.lib.Foo` and `domain.app.vendor.lib.foo`. Reaching one physical directory through two such identities changes neither ownership nor the diagnostic. The physical directory remains a resolution fact, never a substitute identity. Production, same-package test (`ptest`), external test (`pxtest`), and product-scoped recompiled actions share their one exact ordinary package representative and do not re-register as different packages. External compiler identity may still carry `_test`; that action path is not the folded package key. Copy-on-write clones copy exact identity and do not register. Generated main has no ordinary import identity and does not register. Ordinary toolchain package `test` registers like any real package; only the reserved synthetic `__wwtest` role stays outside the ordinary representative table. #### Selected source basenames Directory enumeration first excludes leading-dot, leading-underscore, wrong-platform, and variant-ineligible files, validates the selected regular sources, and byte-sorts their names. Before delegation, the coordinator performs its required package-clause classification and parses selected production files to reject `@test` declarations outside `*_test.ww`. The delegated driver then registers each selected basename in a second request-only table scoped by canonical physical directory. Repeated views of the exact same selected basename across `p`, `ptest`, or `pxtest` are accepted. Distinct fold-equivalent basenames reject as `ww: case-insensitive file name collision: "File.ww" and "file.ww"` before the driver's graph-import scan or any producer. The preflight is not an earlier replacement for the coordinator-owned source validation parse. One `ww test` request shares that directory scope across production, same-package test, external test, same-only, external-only, and mixed test-only actions while preserving their separate compilation units. This catches a collision crossing classifications, such as production `X_TEST.ww` and test `x_test.ww`. An ordinary `ww build` excludes `*_test.ww` before registration. Hidden, underscore-prefixed, and wrong-platform files never register and therefore create no collision or invalidation. This last ordering is WW's explicit applicability boundary rather than a claim that every upstream `AllFiles` member is selected here. Go includes test files and some ignored Go files in `AllFiles`, so its ordinary build can diagnose a broader set. WW intentionally follows its existing fixed-target source eligibility and build/test isolation: files it does not load have no graph or persistence effect. Filesystem basenames are arbitrary non-NUL bytes, so their fold keys reproduce the pinned Unicode 15.0 `unicode.SimpleFold` minimum-cycle behavior without locale or normalization. Each malformed UTF-8 byte contributes one U+FFFD to the temporary key, as Go string ranging does; diagnostics preserve the exact original byte and quote it as `\xNN`. Printable Unicode remains UTF-8, other nonprinting runes use Go-style `\u` or `\U` escapes, and composed/decomposed Unicode spellings are not normalized. #### Tool, artifact, transaction, and persistence ownership The coordinator owns initial eligibility and production/test classification; the delegated driver loader owns both fold checks. The language parser still owns the exact import occurrence and qualifier. The driver owns per-site self, internal, vendor, and imported-main structural legality, while the compiler checker owns file-local binding, use, and visibility. The export writer/reader owns exact canonical `.wwi` data. Compiler, assembler, archiver, and linker protocols did not change. Successful neighboring units, `.wwi`, assembly, objects, archives, generated mains, binaries, and exact tool argv therefore remain byte-identical in Cstage and WWstage. All root and reachable dependency loading, fold registration, and final exact identity binding finish before scratch acquisition, support or generated-main producer work, compilation, assembly, archive construction, or linking. A collision invokes none of those tools and creates no unit, `.wwi`, assembly, object, archive, main, binary, result, status, voucher, stamp, or `.new` stage. Request-wide publication remains transactional: committed sibling and dependency bytes survive a newly introduced collision, and removing the colliding source restores precise warm reuse. The fold tables live only for one command and are freed at graph teardown. Entries become live only after every owned string and vector allocation succeeds, so allocation failure cannot publish a partial table or make cleanup traverse uninitialized entries. Successful action/unit/storage content did not change; build workdir format stays `18`, test workdir format stays `19`, and semantic storage stays `3`. A format bump would only discard valid exact-key artifacts and is therefore not used. Native proof extends `package_graph_diagnostics_are_stable`, `platform_filename_source_selection`, and `vendor_directory_import_resolution`, with command-global allocation failure retained in `allocation_failure_is_command_global`. The matrix covers direct, transitive, reversed, recursive, same-directory, and vendor-expanded imports; exact-repeat acceptance; reversed vendor import and product order; production/internal/external/test-only filenames; reversed creation and direct/recursive collision-diagnostic parity; cross-classification, Unicode, invalid UTF-8, ignored files, and absence of normalization; zero-tool rejection; multi-product publication isolation; cold/warm add-remove reuse; exact artifact preservation; and Cstage/WWstage diagnostic and byte identity. ### 11.24 Implemented package-source test execution directory Every coordinator-executed directory-package test product now runs its one generated binary from the canonical physical source directory of the selected package. The child also receives the corresponding effective `PWD`. This is runtime metadata for the directory product, not canonical package or action identity. #### Pinned Go evidence and pre-fix WW behavior The authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `go test` documents that each listed package is tested by a separate binary, that `testdata` is ignored by package discovery so it can hold ancillary files, and that a command-run binary executes in the corresponding package source directory ([`cmd/go/internal/test/test.go`, lines 64–75 and 411–440](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L411-L440)). The same text says that a generated test binary invoked directly may require the user to enter that directory first; the source directory is not embedded in the executable. - `runTestActor.Act` creates the command, assigns `cmd.Dir = a.Package.Dir`, clips the original environment, appends `PATH`, calls `base.AppendPWD(env, cmd.Dir)`, assigns the environment, attaches output, and runs the command ([`test.go`, lines 1661–1697](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1661-L1697)). The run action retains the original package rather than deriving a directory from `ptest`, `pxtest`, or `pmain`. - `AppendPWD` requires an absolute directory and appends `PWD=` without replacing inherited entries ([`cmd/go/internal/base/env.go`, lines 15–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/base/env.go#L15-L27)). Go's `os/exec` applies last-value-wins duplicate elimination to an explicit environment by scanning backward, retaining the last key, and restoring the surviving order ([`os/exec/exec.go`, lines 1246–1308](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/exec/exec.go#L1246-L1308)). On the pinned Linux boundary, all inherited exact uppercase `PWD=` entries are therefore superseded by the appended package value. Keys remain case-sensitive; `pwd=` and malformed non-key entries are not `PWD`. - Loader `Package.Dir` is the source directory and remains a separate field from `ImportPath`; the command loader copies it from `go/build.Package.Dir` ([`cmd/go/internal/load/pkg.go`, lines 63–76 and 395–402](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L63-L76)). `go/build` likewise owns source location separately from import identity ([`go/build/build.go`, lines 436–451, 521–525, and 612–624](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L436-L451)). - Official scripts use files, directories, and executable fixtures relative to the tested package and mutate ordinary data between test invocations ([`test_cache_inputs.txt`, lines 57–98 and 194–305](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_cache_inputs.txt#L57-L98)); exercise recursive discovery from a symlink root without following nested directory symlinks ([`list_symlink_dotdotdot.txt`, lines 1–20](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/list_symlink_dotdotdot.txt#L1-L20)); and keep multi-package compile-only output separate from execution ([`test_compile_multi_pkg.txt`, lines 3–38](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_compile_multi_pkg.txt#L3-L38)). Before this slice, both WW stages ran directory products from the coordinator's invocation directory. With deliberately duplicated inherited entries, `getcwd` returned that caller directory while WW's first-match `os.getenv` returned the first unrelated `PWD`. `data.txt` and `testdata/input.txt` were therefore read from the caller, and relative writes from parallel products collided there. Production and test-only dependency initializers inherited the same incorrect process context. Direct, recursive, redundant, absolute, and root-symlink spellings already converged on one product but did not use its stored directory for execution. Cstage and WWstage had identical pre-fix output and binaries. #### Directory-product ownership and identity separation The package coordinator already canonicalizes each selected source directory to one absolute, symlink-free physical spelling, rebuilds its selected source paths below that directory, sorts and deduplicates them, and stores the result as `pkggroup.dir`. Relative, absolute, redundant-component, direct, recursive, reversed-root, filesystem-order, and root-symlink requests that reach one package therefore retain the same physical product directory. WW's deliberate applicability boundary differs from Go only where Go preserves a loader-owned symlink spelling: WW uses its already specified canonical physical spelling. That directory is an execution-context field. Exact case-sensitive dotted package identity still owns graph interning, import bindings, mangled symbols, `.wwi` ownership, action and storage keys, archives, diagnostics, and link closure. Declared package name, source alias, path leaf, filename, artifact basename, output path, test action name, and physical-directory equality do not become canonical identity. No physical path was added to a unit, export, symbol, archive, generated main, action digest, product name, status, voucher, stamp, or persistence key. One `pkggroup` owns the process for production plus internal tests, production plus external tests, the combined shape, internal-only, external-only, and mixed test-only directories. Production `p`, augmented `ptest`, external `pxtest`, product-scoped recompiled actions, support, and generated main remain separate actions and derive no independent cwd. The one directory product supplies its `dir` to the one executed binary. #### Child cwd, environment, and concurrency Only `pkgstartrun` sets the existing `exec.command.dir` to `pkggroup.dir`. `lib/os/exec` opens the absolute stdout/stderr captures in the parent, copies argv and environment, forks, and calls `chdir` only in the child immediately before `execve`. The executable, `argv[0]`, captures, product scratch, and coordinator publication paths are absolute, so the child directory cannot reinterpret them. No runtime coordinator-global `chdir` was added; its cwd and `PWD` remain unchanged. Each started product also receives a newly allocated run environment. Section 11.36 supersedes this slice's former test-process locale and temporary-directory policy: the vector is now a Go-like original-environment snapshot. It keeps the first occurrence of each normal case-sensitive key, omits later normal duplicates and raw empty entries, preserves nonempty malformed entries, excludes inherited uppercase `PATH` and `PWD`, and then appends the selected toolchain `PATH` and `PWD=`. Caller `LC_ALL` and `TMPDIR` therefore reach the user test; build-plan tools retain their separate pinned values. The vector, normalization table, and generated strings are product-local, dynamically sized, and published only after every checked allocation succeeds. Partial failure frees only initialized owned storage and never frees borrowed inherited strings. The normalization table is gone before launch. `exec.start` synchronously deep-copies the command before returning, after which the coordinator frees its run vector, generated `PATH`, generated `PWD`, generated `-package` argument, and argv vector. Concurrent children therefore hold independent fork snapshots; no shared environment vector or process-global state is mutated. All dependency initialization occurs inside that product process. A production or test-only dependency reached by package `p` sees `p`'s directory. If the dependency is separately selected as its own test product, that second process sees the dependency's directory. Filters, no-match filters, and list mode use the same binary and context whenever they execute. With multiple products and `-j N`, each child independently observes its own directory and fixture names; emission remains byte-sorted and identical to `-j 1`. #### Nonexecution paths, tools, and direct binaries `ww build` starts no test process. Directory `ww test -c`, including `-c -o`, builds or publishes but never enters `pkgstartrun`; no execution cwd or run environment is allocated. A published binary subsequently invoked by the user bypasses the coordinator and inherits the user's cwd and environment. The raw single-file test compatibility route retains its caller cwd, `PWD`, stdin, and stream behavior, but section 11.32 applies the test-process `PATH` rule at its driver-owned launch. A directory with no selected test source still creates no support, generated main, link, run, result, or execution-context state. Build-plan commands retain `dir=""` and their existing tool environment. Compiler, assembler, in-driver archiver, linker, support generation, and generated-main construction therefore retain their exact prior cwd, argv, and environment. The directory cwd rule required no `lib/os/exec`, compiler, checker, writer, assembler, linker, or driver change; the later test-only PATH rule is isolated at launch and changes neither build-plan environment nor those tools. Independent Cstage/WWstage compile-only products remain byte-identical, and changing only `data.txt` or `testdata` changes no unit, `.wwi`, assembly, object, archive, generated-main, or binary bytes. #### Failure, cleanup, persistence, and proof A missing product directory after a successful build fails the child's `chdir`. The executor reports the positive errno through its setup marker as `termination.ERROR`, distinct from a program exit 127. The coordinator emits `FAIL DIR [package] (test harness error ERRNO)`, treats it as execution/setup failure rather than loader failure, retains successful compilation, continues independently schedulable siblings, and removes its owned captures and scratch under the existing execution-failure contract. It never changes the parent or a sibling's cwd/environment. Execution cwd and `PWD` are request-time process metadata. There is no test result cache, and runtime failure does not invalidate already committed build artifacts. A warm persistent request still performs the established final relink, but no compiler or assembler work; changing only fixture data causes no additional producer work or persistent-byte change and the next always-run test immediately observes the new data. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage remains `3`. The focused native owner is `directory_test_execution_working_directory` in `test/package/package_test.ww`. It creates only disposable source trees and compares Cstage and WWstage across duplicate and large environments; exact `getcwd`, effective/count/position of `PWD`; absent, empty, nonempty, and duplicate inherited `PATH`; ordinary data, `testdata`, and relative writes; all production/internal/external/test-only shapes; production and test-only dependency initialization; recompiled external self-import; direct/recursive/redundant/absolute/symlink roots; reversed roots and creation order; `-j 1`/parallel execution; filters/list/no-match; failure and timeout; no-test and build paths; `-c`, `-c -o`, running retained tests, direct binaries, and raw single files; original test variables and exact tool cwd/argv/locale/TMPDIR/PATH; persistent data-only reuse and artifact/binary identity; and a deterministic post-build directory removal where the affected product reports `ENOENT` while its sibling succeeds. Checked command-global allocation-failure parity remains owned by `allocation_failure_is_command_global`; the focused observer additionally crosses the former fixed environment-size boundary and verifies that no partial execution environment or staged `.new` state is published. ### 11.25 Implemented null standard input for captured actions Every process launched through WW's captured asynchronous executor now receives an explicit fd 0. An empty `exec.command.stdinpath`, which is the production default, opens the null device read-only; a nonempty value opens that exact path. Consequently every coordinator-executed directory test product observes immediate EOF instead of inheriting and consuming the invoking terminal, pipe, or file. Captured directory build plans and the compiler, assembler, and linker processes that inherit their stdio receive the same noninteractive boundary. #### Pinned Go evidence and pre-fix WW behavior The authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `runTestActor.Act` constructs an `exec.Cmd`, assigns its package directory, environment, stdout, stderr, cancellation, and wait delay, and invokes `Run` without assigning `Stdin` ([`cmd/go/internal/test/test.go`, lines 1661–1697](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1661-L1697)). - `Cmd.Stdin` specifies that a nil value reads from `os.DevNull`; `childStdin` opens that device and retains the file for the child; and `Start` installs it as the first child file before process creation ([`os/exec/exec.go`, lines 193–206, 531–538, and 710–738](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/exec/exec.go#L193-L206)). - The ordinary build-command path has the same default. `Shell.runOut` creates an `exec.Cmd`, assigns output, directory, and environment, and runs it without assigning `Stdin` ([`cmd/go/internal/work/shell.go`, lines 600–663](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/shell.go#L600-L663)). - Official `os/exec` tests define a `cat` helper that copies stdin to EOF and require that helper to terminate successfully when run with no `Stdin` assignment ([`os/exec/exec_test.go`, lines 201–204 and 416–459](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/exec/exec_test.go#L416-L459)). The command testdata separately exercises deliberately supplied stdin-pipe lifetime and closure for orphaned test descendants ([`cmd/go/testdata/script/test_timeout_stdin.txt`, lines 1–21 and 39–88](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_timeout_stdin.txt#L1-L21)); that script is adjacent stream-lifetime evidence, while the default null-fd conclusion comes directly from the implementation chain above. Before this slice, `lib/os/exec.start` redirected only stdout and stderr. A directory driver invoked with a nonempty stdin file passed the same open file description through the top-level inherited-stdio handoff, the package coordinator, its captured builder, and the generated product. Serial products could consume caller data; parallel products raced on the shared file offset; a test that waited for input could wait on an interactive caller. Direct measurement with a one-byte pipe made the same directory `@test` fail under both Cstage and WWstage because its first read returned that byte. The raw single-file route also read the byte and failed, but that route intentionally remains inherited-stdio compatibility behavior. #### Descriptor ownership, action boundaries, and concurrency `exec.start` validates `stdinpath`, selects `/dev/null` for the empty value, and opens the input before creating either output capture. `safefd` moves all three standard streams above fd 2 when a caller had closed a standard descriptor. After fork, the child maps the owned input to fd 0 before mapping the captures to fd 1 and fd 2; setup failures travel through the existing close-on-exec marker. The parent closes its input copy immediately after fork. Every pre-fork error path closes every successfully acquired descriptor. The package coordinator does not read or mutate its own fd 0. Each captured build or run child opens an independent null descriptor, so `-j N` products share neither readable caller data nor an input offset. Production, internal, external, recompiled-for-test, support, and generated-main actions still form the same graph and the one directory product still owns one process. Package and test-only dependency initialization observes EOF inside that process. Filters, list mode, no-match execution, failure, and timeout use the same boundary. Standard input is request-time process metadata only. It does not enter canonical dotted identity, declared-name binding, actions, units, exports, symbols, archives, generated main, executable bytes, product names, storage keys, or diagnostics. The source path accepted by `stdinpath` is an executor resource, not a package or filesystem-identity input. #### Inherited-stdio routes, failure, persistence, and proof `exec.runstdio` remains unchanged. The top-level driver therefore preserves inherited stdin for raw single-file tests and runs, and a published test binary invoked directly receives its invoker's fd 0. Directory `ww test -c`, including `-c -o`, starts no product; the compiled binary acquires no embedded stdin policy. No-selected-test packages likewise start no product. Directory build and compile-only plans are captured actions and therefore noninteractive, but their output, cwd, environment, graph, and publication rules are unchanged. Failure to open an explicit input path or the default null device is a pre-fork `termination.ERROR` with positive errno. Because input opens first, neither output capture exists. A child-side `dup2` or close failure is reported through the setup marker, distinguished from exit 127, and follows the existing process-group cleanup path. Test failures, timeouts, post-build directory removal, sibling isolation, transaction rollback, and scratch removal retain their prior contracts. No test-result cache exists. Caller stdin bytes never affect source actions or persistent artifacts, and changing only the explicit proof input causes no compile or assemble work beyond the established warm final relink. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage remains `3` because no persisted byte schema changed. The focused native owner remains `directory_test_execution_working_directory` in `test/package/package_test.ww`. It now drives every relevant command with a known nonempty input file and requires EOF across all directory action/test variants, production and test-only dependency initialization, serial and parallel products, filters/list/no-match, recursive and equivalent roots, failure, timeout, persistent cold/warm/data-only runs, and post-build child setup failure. Tool wrappers require EOF without changing cwd, argv, locale, or `TMPDIR`. Direct published and raw single-file binaries must instead read the supplied data. The observer also proves input-open failure creates no captures, source-class rejection creates no persistent state, Cstage/WWstage diagnostics and output match, compile-only binaries are equal, persisted artifact bytes do not change, and no `.new` residue survives. ### 11.26 Implemented combined ordered test-product output Every coordinator-executed directory-package test product now maps its standard output and standard error to one product-local open capture. The coordinator emits that capture on stdout after the product completes, preserving the order in which writes from either descriptor reach the shared output. Runtime and child-setup status lines are stdout product diagnostics. WW no longer drains two captures and emits all stdout before all stderr. #### Pinned Go evidence and pre-fix WW behavior The authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `runTestActor.Act` selects one output writer for the test action: direct stdout, JSON conversion, stdout plus a buffer, or a private buffer ([`cmd/go/internal/test/test.go`, lines 1436–1499](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1436-L1499)). - It assigns that same writer to both `cmd.Stdout` and `cmd.Stderr`, then runs the test binary ([`test.go`, lines 1661–1697](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1661-L1697)). Success and runtime-failure status text is written through `cmd.Stdout` ([`test.go`, lines 1712–1769](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1712-L1769)). - `os/exec.Cmd` documents its shared-writer rule; `childStderr` returns the already prepared stdout child file when the writers compare equal; and `Start` installs the returned files as descriptors 1 and 2 ([`os/exec/exec.go`, lines 208–225, 565–606, and 710–738](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/exec/exec.go#L565-L606)). - Official command testdata has test mains write only to `os.Stderr`, requires those bytes on `go test` stdout in buffered and streaming forms, and requires command stderr to remain empty ([`cmd/go/testdata/script/test_fail_newline.txt`, lines 3–35 and 42–65](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_fail_newline.txt#L3-L65)). The adjacent orphan-I/O test forwards a descendant's stderr through the test process and likewise requires the bytes on command stdout ([`test_timeout_stdin.txt`, lines 9–21 and 39–82](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_timeout_stdin.txt#L9-L82)). The output destination is explicit in the pinned implementation and official testdata. The ordering conclusion is source-derived: equal writers reuse one child file or pipe instead of two independently drained pipes. No installed host Go behavior is authority. Before this slice, `pkgstartrun` supplied distinct `test.stdout` and `test.stderr` paths. `exec.start` opened independent files, and `pkgemitgroup` later emitted the entire stdout file followed by the entire stderr file on different coordinator descriptors. A direct both-stage probe that wrote `OUT-1`, `ERR-1`, `OUT-2`, `ERR-2` by alternating syscalls therefore reported `OUT-1`, `OUT-2` on stdout and `ERR-1`, `ERR-2` on stderr. Cstage and WWstage had byte-identical pre-fix behavior. #### Descriptor and product ownership The reusable captured executor owns only the descriptor mechanism. When `stdoutpath` and `stderrpath` are byte-equal, it opens the path once with the existing exclusive mode and obtains a close-on-exec duplicate from the same open file description. The child maps those owned descriptors to fd 1 and fd 2. Distinct paths retain independent exclusive opens and their prior behavior. Path equality here selects an executor resource; it creates no filesystem, package, import, action, symbol, artifact, or persistence identity. The package coordinator owns the policy. One `pkggroup` now allocates one `runoutput`, supplies it for both child paths, reads it once, and writes it to coordinator stdout. Production, internal, external, recompiled-for-test, support, generated-main, and test-only actions retain their exact topology and one directory product still owns one process. Dependency initialization and test bodies share the product descriptors naturally; no source rewriting or manual stream forwarding exists. Individual writes by one process retain syscall order. Descendants inheriting the descriptors share the same open output, with ordinary kernel scheduling for concurrent writers. Different products never share a capture. `-j N` may run products concurrently, but the coordinator still waits for completion and emits complete captures in canonical group order, so serial and parallel command byte streams remain identical. #### Diagnostics, nonexecution, and inherited routes Successful and failing test-binary bytes, including bytes written to fd 2, are emitted on stdout. A nonzero product, signal-classified test, timeout, or child setup failure appends the existing `FAIL DIR [package] (test ...)` status on stdout. Loader, source, compiler, assembler, linker, build-action, allocation, capture-read, and cleanup diagnostics keep their established stderr channel; captured build-plan stdout and stderr remain separate. `ww build`, directory `ww test -c` (including `-c -o`), and a directory with no selected test source start no product and allocate no run capture. A published test binary invoked directly and the raw single-file compatibility route bypass the coordinator, inherit fd 1 and fd 2 independently, and retain the caller's stream destinations. `exec.runstdio` is unchanged. An arbitrary `exec.command` with distinct output paths is also unchanged. #### Failure, persistence, cleanup, and proof Input still opens before any output. A merged output open failure creates no child and no second capture. Duplicate, fork, descriptor-map, `chdir`, and `execve` failures use the existing checked setup marker and close every owned descriptor. Product failure does not erase successfully committed compilation; sibling products retain independent output, process groups, and cleanup. The coordinator removes its product captures with the existing temporary root, and rejection or rollback publishes no partial result or `.new` state. Output routing is request-time process metadata. It changes no unit, export, assembly, object, archive, generated main, binary, action/storage key, tool record, stamp, or persistent byte. There is still no test-result cache. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage remains `3`. The executor-level native proof in `test/wwfixture/process/main.ww` requires distinct captures to stay distinct and equal paths to preserve alternating fd-1/fd-2 bytes through one file in both compiler stages, including when the caller closed stdout and stderr. The package owner `directory_test_execution_working_directory` alternates real writes through production and test-only dependency initialization; production/internal, external, combined, recompiled, and test-only products; filters, list, and no-match execution; success, assertion failure, signal, timeout, and post-build `chdir` failure; serial/parallel and equivalent-root requests; cold/warm/data- only persistence; and direct/raw boundaries. It requires Cstage/WWstage output and diagnostics to match, failure/setup trailers to use stdout, successful outer stderr to be empty, direct/raw stderr to remain separate, artifacts and binaries to remain byte-identical, and every temporary or staged path to be cleaned. ### 11.27 Implemented Go-like directory test-binary retention Directory-package `ww test` now separates the request-private executable that the coordinator may run from the optional caller-visible executable it retains. `-c` means retain without running; `-o` means retain at the requested location and still run unless `-c` is also present. Output naming, directory fan-out, duplicate-name preflight, exact null-device discard, executable mode, and no-test behavior follow the applicable Go 1.26.5 contract. #### Pinned Go evidence and direct pre-fix measurements The authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `CmdTest.Long` directly states that `-c` writes `pkg.test` in the current directory and does not run it, while `-o` saves a copy and still runs unless `-c` is present; a trailing slash or existing directory receives `pkg.test` ([`cmd/go/internal/test/test.go`, lines 150–168](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L150-L168)). - `testNeedBinary` makes nonempty `-o` an independent retention request ([`test.go`, lines 631–646](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L631-L646)). `runTest` recognizes an existing directory or trailing separator, rejects a multi-package non-directory output, and preflights every selected package for duplicate test-binary names before builder execution, except when the output is the null device ([`test.go`, lines 771–804](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L771-L804)). - `builderTest` takes the ordinary production-only branch when no test files exist, creating no test link or retained binary ([`test.go`, lines 1133–1169](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1169)). A real test first links into its action object directory; `-c` or binary retention adds an install action, only `-c` selects the no-op print action, and the non-`-c` run action depends on the original build action rather than the installed copy ([`test.go`, lines 1200–1313](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1200-L1313)). - `testBinaryName` explicitly uses the final import-path element rather than the declared package name; its command-line-files exception uses the source package name ([`test.go`, lines 2287–2300](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L2287-L2300), [`cmd/go/internal/load/pkg.go`, lines 1727–1769](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1727-L1769)). - `BuildInstallFunc` creates parents and installs a linked executable with mode `0777` filtered by the process umask ([`cmd/go/internal/work/exec.go`, lines 1904–2000](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1904-L2000), [`cmd/go/internal/work/shell.go`, lines 119–220 and 283–301](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/shell.go#L119-L220)). On the pinned Unix target, only exact `/dev/null` is the null spelling ([`cmd/go/internal/base/path.go`, lines 81–92](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/base/path.go#L81-L92)). - Official `test_compile_multi_pkg.txt` requires missing nested output directory creation, default current-directory output, rejection of a non-directory multi-output and duplicate names, `/dev/null` acceptance, and `-o DIR` retention while tests still run ([lines 3–38](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_compile_multi_pkg.txt#L3-L38)). The separation between saved and executed paths is a conclusion derived from the pinned action dependencies: the run consumes the temporary link action, not the install action. Duplicate names are likewise a materialization collision, not package identity. Section 11.31 completes the later install dependency: compile-only products retain the request transaction, while a running retained product installs independently only after its successful run. No installed host Go behavior was used as authority. Before this slice, direct native measurements of both Cstage and WWstage showed that single-package `-c -o FILE` retained and did not run, but `-o FILE` without `-c` exited 2 with `-o needs -c for a package target`; multi-package `-c -o FILE` exited 2 with the older unconditional fan-out rejection. Default multi-package `-c` scattered `.test` binaries into their source directories. Those measurements used the public driver route and observed exits, diagnostics, files, executable behavior, and stage-equal bytes; they were not conclusions drawn from WW source. #### Coordinator policy and identity boundaries `internal/wwpackage.packagecommand` is the sole owner of public output policy. It resolves the invocation directory, computes each visible `.test` name, recognizes output-directory and `/dev/null` forms, rejects non-directory fan-out and duplicate names, omits publication for no-test products, and schedules execution according to `-c`. A contextual dotted request uses its exact final component; a local path request uses its directory leaf as the manifest-free presentation equivalent. Neither becomes declared-name or physical-directory identity. Every actual test product still links to `package.test` below its private plan root. The private descriptor carries that `OUTPUT` plus an optional absolute `PUBLICATION`. The Cstage and WWstage drivers implement only this symmetric mechanism; they do not independently decide names or CLI policy. The coordinator always executes `OUTPUT`, so `-o` cannot alter executable argv, cwd, environment, null stdin, combined output, filters, action topology, or test outcome. Visible basename, publication path, private runnable path, declared family, physical source directory, production/internal/external/recompiled/support/main variants, symbols, `.wwi`, archives, action identity, and persistence keys remain distinct. A duplicate basename rejects only the requested materialization. It never merges, renames, folds, or rekeys either canonical package. Compiler inputs, exported interfaces, generated main, archive order, and linked bytes are otherwise unchanged. #### Publication, execution, failure, and cleanup Without explicit `-o`, `-c` retains each binary in the invocation directory. An existing directory or a path ending in `/` receives one visible name per selected package; missing parents are created with `0777` subject to umask. A non-directory destination accepts exactly one selected package. Exact `/dev/null` suppresses retained copies, permits duplicate visible names, and does not suppress execution unless `-c` is also present. A no-test package performs ordinary production validation, reports `[no test files]`, and creates no binary or otherwise-unused output directory. Successful test-bearing compile-only products are silent, matching Go's no-op print action. For `-c`, the driver copies the private runnable bytes to a distinct `.new` inode opened with executable mode `0777` subject to umask. Temporary runnable, retained copy, statuses, changed persistent actions, tool records, and stamp then enter the existing one-request transaction. All producers and linkers complete before installation. Any load, compile, assemble, archive, link, stage, or install failure preserves old retained binaries and persistent bytes, discards all stages, removes cold scratch, and rolls back only output prefixes created by that request. Occupied or dangling `.new` paths reject before tools and are never overwritten. For running `-o`, the build transaction commits only the private runnable, status, and semantic actions. The coordinator executes that runnable and, on a successful result, invokes the selected driver stage's public install action. Assertion failure, signal, timeout, interruption, or child-setup failure skips that action and preserves any prior binary. Successful parallel products install independently after their runs; canonical result emission order stays unchanged. Direct invocation of a retained binary continues to inherit caller cwd, environment, and separate standard descriptors. `-c` and `-o` can accompany `-w`: the workdir owns only semantic actions while the invocation/output path owns only the retained copy. Unchanged actions are reused, changed source invalidates the applicable test actions, and the always-run link refreshes the private runnable and retained copy. Only `-c` suppresses execution. This is build reuse, not a result cache. No persisted byte schema changed. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage remains `3`. The focused native owners are `compile_artifact_naming` and `test_binary_publication_transaction` in `test/package/package_test.ww`. Their Cstage/WWstage matrix covers single/default/directory/nested/multi/null output; declared-name versus import-leaf naming; executable mode and direct execution; temporary argv versus retained path; no-test omission; duplicate and non-directory rejection; occupied stages; serial and parallel sibling publication; injected late-link rollback over old files and newly created parents; runtime-failure preservation; persistent cold/warm/invalidation behavior; diagnostic equality; retained binary byte identity; and absence of `.new` residue. Existing package tests continue to own all action/test variants, graph identity, output ordering, cwd/environment/stdin, timeout, and broader transaction behavior. ### 11.28 Implemented Go-like build-output permissions Newly published build outputs now use Go 1.26.5's output-kind permission and caller-umask contract. An ordinary linked command starts from `0777`; a non-link archive starts from `0666`. The kernel filters either base permission through the invoking process's umask when the request-private publication inode is created. WW's required adjacent interface sidecar is data like its archive and uses the same `0666` base. Assembly-only builds create neither kind of public output. #### Pinned Go evidence and direct pre-fix measurements The authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `runBuild` routes explicit single and directory `-o` products through `ModeInstall`, after deciding the caller-visible output path ([`cmd/go/internal/work/build.go`, lines 459–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L558)). - `BuildInstallFunc` begins with permission `0666`, changes it to `0777` for an ordinary link action, creates the output parent, and gives that permission to `moveOrCopyFile` ([`cmd/go/internal/work/exec.go`, lines 1904–2000](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1904-L2000)). - On its rename path, `moveOrCopyFile` creates a destination-adjacent dummy with the requested permission, observes the caller-filtered mode, removes the dummy, applies that mode to the linked source, and renames it. Its copy fallback creates the destination with the requested permission and therefore receives the same kernel filtering ([`cmd/go/internal/work/shell.go`, lines 119–220](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/shell.go#L119-L220)). - Official `build_output.txt` asserts executable default, explicit-file, nested-file, trailing-directory, and existing-directory command outputs ([lines 7–44](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_output.txt#L7-L44)). `build_multi_main.txt` exercises directory fan-out for two main packages and a local command-line package ([lines 1–16](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_multi_main.txt#L1-L16)). The testdata anchors directly specify that the public command routes produce executables. The exact `0777`/`0666` bases and caller filtering are implemented by the pinned source. Therefore the resulting mode formula is source-derived; it is not an observation of the installed host Go toolchain. Before this slice, fresh public-driver measurements of one byte-identical command gave mode `0755` from both stages under umask `000`. Under umask `077`, Cstage still gave `0755` while WWstage gave `0700`. The C linker created through `fopen` and unconditionally applied `chmod(0755)` after emission; the WW linker created with base `0755`. Thus both discarded permitted group/other write bits, and Cstage additionally reintroduced bits forbidden by a restrictive mask. The non-link branch had a separate stage mismatch under the same official rule. With umask `000`, Cstage published a byte-identical archive/interface pair as `0666` while WWstage published it as `0644`; both became `0600` under umask `077`. Cstage's fresh `fopen` data stage already had base `0666`, while WWstage's data-copy stage explicitly used base `0644`. #### Ownership, publication, and identity boundaries The C and WW linkers now open every fresh linked output with base `0777`. The C linker emits through the resulting descriptor instead of applying a fixed mode afterward; the WW linker uses the same creation base. The WWstage driver's archive/interface copy now uses `0666`, matching Cstage's existing data-file creation. No driver independently reads or stores a umask. For public build routes, the coordinator has already rejected an occupied or dangling output `.new` before the selected linker or copy owner opens the request-private stage. Creation therefore receives the current child process's umask exactly once. The established transaction renames that same inode to the caller-visible destination, so neither the final name nor replacement of an old destination changes its mode. A failed compiler, assembler, archiver, linker, stage, or installation preserves the old destination's bytes and mode and removes all request stages. Directory fan-out gives each independent command the same request-local rule; concurrent driver processes retain independent umasks and publication paths. Permission bits are presentation metadata, not semantic inputs. Package and action identity, graph edges, declared names, physical directory metadata, compiler/assembler/archive/link argv, `.wwi` contents, artifact bytes, and persistence keys are unchanged. An unchanged warm request may reuse every semantic action but still relinks or copies the requested public product so its mode reflects the current invocation. Source invalidation changes the applicable artifact bytes without changing the formula. Retained test-binary copying remains a distinct output-policy path and already uses the same `0777` linked- executable rule. No Go-style dummy is needed and no `-go-tmp-umask` residue is created because WW links or copies directly into its already-private fresh stage. No persisted byte schema changed. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage remains `3`. The WW-native owner `build_output_permissions_follow_umask` uses a test-only exec launcher to arrange exact process umasks. It covers both Cstage and WWstage; cold, warm, and invalidated persistent builds; explicit, default, raw-file, and multi-command directory outputs; `0777`, `0700`, `0750`, and `0770` command results; `0666` and `0600` archive/interface results; assembly-only omission; retained test-binary non-regression; direct execution; injected late-link request rollback over old files and modes; occupied-stage rejection; simultaneous builds with different umasks; diagnostic parity; artifact and binary byte identity; and absence of `.new` or umask-probe residue. ### 11.29 Implemented exact null-output discard for builds Exact `ww build -o /dev/null` now removes output installation while preserving the ordinary load and action graph. It is not a request to create an archive, executable, interface, or scratch tree at the null-device pathname. #### Pinned Go evidence and fact classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `runBuild` loads packages and reports load errors first, then recognizes the null output and clears `BuildO` before any output-directory, multi-package, or install-action branch. It finally constructs ordinary `ModeBuild` actions for every selected package ([`cmd/go/internal/work/build.go`, lines 459–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L558)). - `AutoAction` maps a main package in that ordinary mode to a link action and a non-main package to a compile action ([`cmd/go/internal/work/action.go`, lines 450–455](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L450-L455)). - On the pinned Unix target, `IsNull` accepts exact `os.DevNull`, which is `/dev/null`; its only additional spelling rule is the Windows-only case-insensitive `NUL` exception ([`cmd/go/internal/base/path.go`, lines 81–92](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/base/path.go#L81-L92)). - The test builder treats a nonempty `-o` as a binary-retention request, exempts the null device from multi-package output rejection, and makes a null target use the private build action instead of an install action ([`cmd/go/internal/test/test.go`, lines 631–646, 771–804, and 1259–1294](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1259-L1294)). - Official `devnull.txt` requires `go test -c -o $devnull` and a non-main package `go build -o $devnull` to succeed without changing the device ([lines 3–25](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/devnull.txt#L3-L25)). `build_dash_o_dev_null.txt` requires a command-line source build to succeed without its default executable ([lines 1–12](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_dash_o_dev_null.txt#L1-L12)). `build_cache_link.txt` requires a cold null build to compile and link and an unchanged warm null build to skip compilation but link again ([lines 4–22](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_cache_link.txt#L4-L22)). `TestRemoveDevNull` requires cleanup never to remove the device ([`cmd/go/internal/work/build_test.go`, lines 22–35](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build_test.go#L22-L35)). The load-before-output order, exact spelling, absence of installation, normal command link, normal non-command compile, cold/warm link behavior, raw-source behavior, and device preservation are directly implemented or asserted by the pinned sources above. Acceptance of multiple mixed package roots and an empty matched set is derived from clearing `BuildO` before the output-cardinality branches and then iterating the ordinary package action list. That conclusion applies to WW's manifest-free local package set without importing Go's module, cache, or distribution model. No installed host Go behavior is authority. #### Direct pre-fix measurements Fresh public-driver probes measured both stages before production edits: - raw source, one command directory, and one non-main library directory each failed with exit 1 and `ww: cannot create scratch /dev/null.sepwork`; - a two-command-plus-library request failed with exit 2 and `wwtest package: cannot use -o with multiple packages`; - a persistent command request reached the linker but failed through `/dev/null.new`: Cstage reported `w6l: cannot open /dev/null.new`, WWstage reported `w6l: cannot open output`, and both left the caller workdir empty; - raw `ww test -c -o /dev/null FILE` and its running form failed at the same adjacent-scratch acquisition, while directory `test -c` and running test requests already built privately, discarded the retained copy, and preserved their compile-only versus run distinction; - a blank import of a missing package produced the same positioned `cannot find package missing.pkg` diagnostic in Cstage and WWstage before output setup; and - `/dev/null` remained the same character device, mode, device/inode, and size throughout the failed probes. Those are directly measured WW facts. The externally observable gap was thus the build/raw-driver interpretation of exact null as an artifact stem, plus the coordinator's ordinary multi-output rejection, rather than a loader, compiler, linker, or device-write defect. #### Ownership, actions, publication, and identity `internal/wwpackage.packagecommand` owns the shared package-request output policy. After argument parsing and before output planning it records exact Unix null discard. Loading, source classification, package/import validation, canonical grouping, graph construction, and diagnostic precedence remain unchanged. The coordinator suppresses default names, output-directory setup, ordinary non-directory fan-out rejection, caller publication, and the visibility-only `-S` workdir requirement, then gives every selected group a request-private plan product. Commands still link; libraries still compile and archive; mixed and repeated roots still use their canonical graph/action deduplication. A recursive pattern matching no package emits its ordinary warning and has no output-cardinality error. The direct Cstage and WWstage drivers own raw or single-directory requests that do not enter the coordinator. For exact null they allocate a private command product, run the unchanged separate-compilation pipeline, and remove that product and its scratch on every return. Their raw-test paths use the existing unretained private test binary rather than setting `/dev/null` as output and object stem. `-c` still suppresses execution; a running request still reports ordinary pass, assertion, signal, and harness outcomes. Directory tests retain their previously established private-runnable/null-publication behavior. There is no caller-visible stage or destination to commit, occupy, replace, or chmod. Producer failure or signal removes private plan state; persistent action rollback preserves every prior unit, interface, assembly, object, archive, tool record, and stamp. Successful persistent requests commit semantic actions normally, unchanged actions are warm-reused, source changes invalidate their owners, and command links still run for each request. Separate simultaneous Cstage and WWstage requests own disjoint private products and workdirs. Exact lookalikes remain normal caller-owned outputs and retain their existing fan-out, `.sepwork`, permission, occupied-stage, transaction, and diagnostic rules. Output disposition remains request metadata. Dotted package identity, declared name, physical source directory, import binding, graph edges, action/storage keys, compiler/assembler/linker semantic argv, symbols, `.wwi`, unit and artifact bytes, and persistent invalidation are unchanged. No persisted byte contract changed: build workdir format remains `18`, test workdir format remains `19`, and semantic storage remains `3`. The WW-native owner `exact_null_output_discards_build_products` covers Cstage and WWstage command, library, mixed-root, raw-build, assembly-only, and raw-test routes; load/import precedence; empty-pattern warning; exact lookalike rejection/publication; cold, warm, and invalidated persistence; normal link actions and captured runnable bytes; injected linker failure and signal; persistent rollback; concurrent stage isolation; device preservation; private path and `.new` cleanup; semantic-artifact and captured-binary byte identity; and diagnostic/output parity. Existing directory-test owners cover test-product parallelism, timeout, child-setup failure, retained-output transactions, and runtime cwd/environment/stdin. Build runtime behavior is inapplicable, and caller-output rollback, occupied caller stages, and output permissions are inapplicable to the exact discard branch because it creates no public inode. ### 11.30 Implemented single-root build output directories An explicit `ww build -o OUT` now treats `OUT` as a directory when ordinary `stat` reports an existing directory or the spelling ends in `/`. The rule is independent of package count. A selected command directory publishes `OUT/` (falling back to the selected local directory leaf when no contextual identity exists); a raw command-line source publishes `OUT/`. A missing trailing-slash hierarchy is created from `0777`, filtered by caller umask, through the existing checked directory ledger. All roots load first, but independently selected non-main roots are omitted from the directory branch's action list. A selection containing no command—including a raw non-main root—rejects as `ww: no main packages to build` without running a producer or changing the output directory. After a lone command's default basename is synthesized, an existing directory at that basename instead rejects as `ww: build output "" already exists and is a directory`; a non-main package has no default public output and is unaffected. #### Pinned Go evidence and fact classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `runBuild` completes package loading and package-error checking before output handling at [`cmd/go/internal/work/build.go`, lines 459–471](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L471). After synthesizing a lone `main` package's default output at lines 473–478, its output branch classifies an existing directory through `os.Stat`, or a spelling ending in `/` or the host path separator, at [lines 508–518](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L508-L518). It then creates install actions only for packages named `main`, targets each at the output directory joined with `DefaultExecName`, rejects an empty command action list as `no main packages to build`, and executes that graph at [lines 519–535](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L519-L535). The non-directory single-output branch is separate at [lines 537–548](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L537-L548). - `DefaultExecName` uses the final import-path element for a directory package and the source basename for command-line files ([`cmd/go/internal/load/pkg.go`, lines 1727–1769](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1727-L1769)). - `BuildInstallFunc` creates the target parent before installation, and `Shell.Mkdir` implements that operation as `os.MkdirAll(dir, 0777)` ([`cmd/go/internal/work/exec.go`, lines 1975–2000](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1975-L2000), [`cmd/go/internal/work/shell.go`, lines 283–301](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/shell.go#L283-L301)). - Official [`build_output.txt`, lines 10–29 and 41–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_output.txt#L10-L45) asserts a raw source's default basename, a missing trailing-slash directory, and an existing directory destination. - Official [`build_multi_main.txt`, lines 1–16](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_multi_main.txt#L1-L16) asserts command fan-out beneath one directory, no-main rejection, the implicit-default-existing-directory error, and raw command-line-source placement beneath an existing output directory. Load-before-output ordering, `stat`/separator classification, command-only installation, import-leaf naming, destination joining, no-main rejection, and the `0777` parent-creation request are directly implemented by the pinned source. Raw-source basename and existing/missing directory behavior are directly asserted by official testdata. The resulting parent mode after umask is derived from the pinned `MkdirAll` call. Application to exactly one directory package is derived from `runBuild`: the directory branch tests output form, not package cardinality, while the cardinality check exists only in the later non-directory branch. These facts apply to WW's local manifest-free command and raw-source products without importing Go's module, cache, registry, distribution, or network behavior. The installed host Go version is not authority. #### Direct pre-fix measurements Fresh public Cstage (`out/bin/ww`) and WWstage (`out/bin/ww_ww`) probes measured the same divergence before production edits: - one command directory plus an existing output directory spelled without `/` returned 0, renamed the caller's directory to a PID-bearing transaction backup, installed a 4,268-byte ELF executable at the directory pathname, and diagnosed failure to remove the nonempty backup; - the same existing directory spelled with `/` returned 1 with `ww: cannot preserve transaction destination .../`; - a missing nested spelling ending in `/` returned 1 while trying to acquire `/.sepwork` before the hierarchy existed; - a raw `main.ww` plus an existing trailing-slash destination failed through the same transaction-destination path instead of producing `OUT/main`; and - a non-main directory plus an existing directory spelled without `/` returned 0, replaced the directory pathname by an archive, wrote its `.wwi` beside that pathname, and stranded the former directory as a transaction backup; and - for both a command directory and a raw command-line source, an existing directory at the synthesized default basename was renamed to a transaction backup and replaced by the executable; both stages returned 0 and diagnosed inability to remove the deliberately nonempty backup. Completion review measured four additional stage-identical pre-completion behaviors before their production edits. A mixed command/non-main request compiled the independent non-main root in both stages; a raw non-main root returned 0 and published an archive plus `.wwi`; a contextual `alias` symlink to physical directory `physical` published `OUT/physical`; and an exactly arranged umask `000` produced newly created output parents with mode `0700`. Pinned Go instead loads then omits the independent non-main action, rejects the raw no-command selection, uses the requested import leaf, and requests parent mode `0777`. The preserved traces and stat results are in the session evidence ledger. Final review then measured four stage-identical load-precedence leaks before the completion edit. A non-main root with a missing import reported only `no main packages`; a command with a missing import and an overlong derived directory destination reported only the path error; two colliding command basenames, one with a missing import, reported only the duplicate-destination error; and a recursive command with a missing import plus an implicit default directory collision reported only the collision. Pinned `runBuild` lines 470–471 load and check all selected packages before any output handling at lines 473–548. Missing-package diagnostics therefore precede no-main, derived-path, duplicate-destination, and implicit-default checks. Extending that boundary to WW's transactional duplicate guard is derived from the pinned ordering because the guard is WW-local output preflight. The exact probes and outputs are preserved in the evidence ledger. Those are directly measured WW facts. Both drivers interpreted every non-null single-root `-o` as one file and object stem. The compiler, assembler, linker, archive writer, and shared package coordinator were not the cause. #### Ownership, actions, publication, and identity `internal/wwpackage.packagecommand` remains the shared package-request output owner. It classifies output directories, discovers and groups the complete selection, and passes every selected root plus output-preflight metadata into the shared separate-build executor. Only after that executor has loaded all packages and imports does it retain command roots, derive their complete action closure, and evaluate no-main, path-length, duplicate-destination, and implicit-default checks. A separate presentation field carries the requested import leaf (or local-path fallback) through collision preflight and publication; canonical physical directory metadata remains loader metadata. The coordinator commits the retained products through one request transaction. The dispatch part of the gap belonged to the early single-root compatibility choice in `cmd/ww.do_build` and `selfhost/cmd/ww.dobuild`; completion review also closed the coordinator's independent-non-main action, physical-leaf-presentation, and load-precedence leaks. After ordinary argument parsing and root resolution, both drivers now apply the same exact Unix classification. A directory root with a directory output enters the existing package coordinator. An explicit logical root carries its unchanged logical root identity while the corresponding argument is replaced by the already-resolved loader route; a default invocation inserts exactly one `.`; a literal directory remains literal. Thus the shared loader, grouping, graph, action, output-preflight, and publication rules operate exactly as they do for a larger request. The raw-file compatibility route remains driver-owned. It derives the joined command path, uses that path as the existing direct action's product and stem, and passes the classified directory to the shared transaction's checked creation ledger. A bounds failure is carried as preflight metadata so source and import errors, and raw no-main rejection, retain pinned load-first precedence before the path diagnostic. It does not manufacture a package request or change raw-source graph identity. `stat` follows a symlinked output directory; lexical publication remains beneath the requested symlink spelling. Exact `/dev/null` is classified first by the completed discard rule and never enters this directory branch. For an implicit default, the drivers pass the existing-directory collision as preflight metadata to the common separate-build executor. The executor waits until package/import loading, contextual checks, and graph-cycle validation have established the root action kind. It rejects a command before scratch, workdir, tool, stage, or destination acquisition, but lets a non-main package perform its unchanged no-public-output build. This keeps raw and directory compatibility routes on the same diagnostic-precedence rule without deriving kind from a path, filename, declared-name guess, or driver-side source scan. Loading and source/import rejection precede every output-derived rejection, including no-main, derived-path length, duplicate destination, and implicit default collision; all precede output creation. A selection with no command rejects after full package/import loading and graph validation but before compiler, assembler, linker, or directory mutation. In a mixed request, independently selected non-main roots have no action; a non-main package reachable as a command dependency still performs its ordinary semantic action. Repeated exact roots retain canonical graph/action deduplication. Successful commands compile, assemble, archive, and link normally; `-S -w` remains action-only and publishes no command. Directory form still selects only commands and therefore retains no-main rejection, but destination length, duplicate publication names, implicit destination collision, and output-parent creation belong to the install action that `-S` never reaches. They are inapplicable to that assembly-only request. An explicit external workdir prevents an adjacent `.sepwork`; without `-w`, that established WW scratch tree remains an ordinary retained build artifact beneath the output directory. Existing destination contents and symlink targets survive successful publication. Compiler failure, linker failure, or linker signal preserves the prior command and every committed persistent artifact, removes `.new` and transaction stages, and rolls back only directory prefixes created for the failed request. Every caller-output prefix is requested as `0777` and filtered once by the caller umask; persistent/private work directories keep their separate modes. The raw route has the same missing-directory rollback through the shared creation ledger. Independent Cstage and WWstage processes use disjoint output, work, stage, and process ownership and may complete concurrently. `ww build` itself has no runtime action; direct execution of the published command verifies its ordinary program exit result, while runtime failure/timeout policy remains owned by `ww run` and `ww test`. This is output disposition and dispatch only. Dotted package/import identity, declared package name, physical source directory metadata, file-local import bindings, graph edges, action and storage keys, symbols, `.wwi`, compiler, assembler, archive and linker semantic inputs, artifact bytes, invalidation, and public-file output-mode formula are unchanged. Correcting caller-output parent creation metadata does not enter any semantic identity. There is no persisted-byte contract change: build workdir format remains `18`, test workdir format remains `19`, and semantic storage remains `3`. The WW-native owner `single_root_build_output_directory` covers literal, logical, default-dot, symlinked, raw-file, explicit existing/missing, and implicit-default existing-directory forms in both stages; basename selection and directory-content preservation; logical alias versus physical-leaf separation; command rejection, raw no-main rejection, non-main no-output behavior, long raw-output and load-error precedence; mixed command-only and repeated roots; skipped-root import rejection; and no-main, directory-derived path, duplicate-destination, and recursive implicit-collision precedence with zero tool activity; exact `0777` missing-parent creation under umask `000`; the already-aligned retained-test control; `-S -w` command selection with no install-only preflight or output-directory creation; cold, warm, and invalidated persistence; exact compiler/assembler/linker action traces; successful program exit results; compiler and linker failure; linker signal; prior-state and newly-created-directory rollback; `.new` and transaction cleanup; concurrent stage isolation; executable and semantic-artifact bytes; and exact diagnostic parity. Existing owners continue to cover public-file output umasks, occupied stages, generalized multi-product transactions, test runtime failure and timeout, null discard, and broader package/import graph matrices. ### 11.31 Implemented Go-like public-output overwrite safety Every caller-visible build and retained-test install now protects an existing destination at the same late boundary as Go 1.26.5. After applicable producers finish, ordinary `stat` rejects a directory and rejects a nonempty regular file whose leading bytes do not identify a toolchain output. Absent paths, empty regular reservations, recognized outputs, and non-directory non-regular paths remain replaceable. Exact `/dev/null` and assembly-only `-S` have no install action and never enter this rule. #### Pinned Go evidence and classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `Shell.moveOrCopyFile` and `Shell.CopyFile` call `checkDstOverwrite` before replacing the destination ([`cmd/go/internal/work/shell.go`, lines 119–235](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/shell.go#L119-L235)). `checkDstOverwrite` uses `os.Stat`, rejects a directory, and—unless forced— rejects a nonempty regular file for which `isObject` is false ([lines 248–261](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/shell.go#L248-L261)). - `BuildInstallFunc` creates the destination parent and reaches `moveOrCopyFile(..., false)` only after its build producer ([`cmd/go/internal/work/exec.go`, lines 1904–2000](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1904-L2000)). `objectMagic` and `isObject` read the first 64 bytes and recognize archive, ELF, Mach-O, PE, Plan 9, WASM, and XCOFF prefixes without consulting a file extension ([lines 2118–2150](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L2118-L2150)). - `runBuild` loads and checks every selected package before constructing the output/install action ([`cmd/go/internal/work/build.go`, lines 459–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L558)). - `builderTest` makes `-c` depend directly on the install action. For a running retained test, the run consumes the private build action and the install action additionally depends on that run ([`cmd/go/internal/test/test.go`, lines 1257–1364](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1257-L1364)). `Builder.Do` invokes an actor only when dependency failure has not propagated (unless the action explicitly ignores failure), so a failed test run skips `BuildInstallFunc` ([`cmd/go/internal/work/exec.go`, lines 72–207](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L72-L207)). - Official `build_output_overwrite.txt` requires refusal to replace a nonempty source file and preservation of its contents ([lines 1–20](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_output_overwrite.txt#L1-L20)). Official `test_compile_tempfile.txt` requires an existing empty reservation to be accepted and replaced ([lines 1–11](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_compile_tempfile.txt#L1-L11)). Official `build_output.txt` separately pins executable command and archive products ([lines 47–57 and 64–76](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_output.txt#L47-L76)). The destination predicate, complete magic table, load-before-install ordering, producer-before-check ordering, and run-before-install dependency are directly implemented by the pinned source. Non-overwrite and empty-file acceptance are directly asserted by official testdata. Applying ELF and archive recognition to WW's byte-identical output forms is derived from that implementation. Go has no WW interface sidecar; recognizing only the compiler-owned `//ww:module ` prefix is the derived local application that permits ordinary repeat publication without letting arbitrary sidecar text be overwritten. No installed host Go behavior was used as authority. #### Fresh four-axis audit and pre-fix measurements The bounded audit selected this one gap on the build axis and the shared retained-test install axis. The package control selected the same canonical command root twice and measured one deduplicated command action plus one dependency action, with byte-identical Cstage/WWstage units, interfaces, and archives. The import control placed a used alias in one source file and an unused alias for the same dependency in a sibling; both stages emitted the same file-local unused-import diagnostic and committed no work. Those package and import candidates were aligned and were not changed. Fresh public Cstage and WWstage probes directly measured the same pre-fix behavior. Explicit command, raw command, output-directory child, library archive/interface, compile-only test, and running retained-test destinations containing arbitrary nonempty text were replaced successfully. A nonempty directory at a build or test child destination was renamed to a PID-bearing transaction backup, replaced by the executable, and left stranded because backup cleanup could not unlink the directory. Empty reservations were already accepted. Missing-import rejection already preceded destination handling. All measured successful executables, archives, interfaces, diagnostics, runtime results, and semantic artifacts were stage-identical. Those are directly measured WW facts, not source inferences. #### Ownership, action order, rollback, and identity The Cstage `sep_txn_commit` and WWstage `septxncommit` publishers own the byte predicate. Each transaction entry now explicitly distinguishes a public install from internal status, tool-identity, stamp, and persistent-action state. Only command/archive output, retained-copy, and published `.wwi` entries are checked. Producers still finish before transaction commit; a rejected destination discards all staged outputs and preserves every prior public and persistent byte. A library archive and interface remain one rollback group, so arbitrary text in either destination changes neither. `internal/wwpackage.packagecommand` continues to own directory-test naming and scheduling. A running retained descriptor withholds its public destination from the build child. After a successful private run, the coordinator invokes a private action in the selected driver, which stages an executable copy and re-enters the same guarded publisher. A failed, signalled, timed-out, interrupted, or unstartable run never invokes that action. Successful products in a multi-package running request install independently; compile-only products retain the established request transaction. The driver-owned raw single-file route applies the same private build, run, and guarded-install sequence. Package-build descriptors use `build-public` only for caller-visible command or archive products. Private package-build placeholders, test runnables, `ww run`, workdir-owned test binaries, null-discard products, and assembly-only products remain internal entries. Destination path, file kind, magic, declared name, requested alias, import leaf, physical directory, and publication order do not enter package/import identity, graph edges, action keys, symbols, artifacts, `.wwi` contents, or persistence keys. The guard follows symlinks for classification, matching `os.Stat`; the existing transaction still replaces the destination directory entry itself. It permits FIFO and other non-directory non-regular destinations because the pinned guard does. Diagnostics are exactly `ww: build output "PATH" already exists and is a directory` and `ww: build output "PATH" already exists and is not an object file` in both stages. No guard is preflighted during loading: package/import errors still win, and compiler, assembler, archive, or linker failure prevents the install action from being reached. Build runtime is inapplicable because `ww build` starts no program. Test runtime is applicable and owns the post-run dependency above. Producer failure, linker interruption, output-parent rollback, concurrency, occupied stages, prior-state preservation, and residue cleanup remain governed by the existing request/private-action transactions; the new check adds no process-global state. Public artifact bytes and modes are unchanged on accepted installs. There is no persisted-byte contract change: build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. The WW-native `public_output_overwrite_safety` observer covers both stages: direct, default, raw, package-output-directory, library, compile-only test, and running-test routes; late linker activity and load precedence; absent/empty, ELF, archive, interface, arbitrary regular, directory, symlink, and FIFO destinations; cold, warm, and invalidated persistent rollback; run-before-check and failed-run no-install behavior; exact null and assembly-only exclusions; runtime results; modes; diagnostic identity; public and semantic artifact-byte identity; and `.new`, install-stage, and transaction-backup cleanup. `test_binary_publication_transaction` pins the changed failed-run behavior and the existing linker failure, output-parent rollback, multi-product, persistent, and retained-binary contracts. Existing request-transaction, timeout, interruption, and concurrent-driver owners continue to cover those unchanged dimensions. ### 11.32 Implemented selected toolchain first in test `PATH` Every test binary actually started by `ww test` now receives one effective uppercase `PATH` beginning with the canonical absolute directory of the selected WW driver. An absent or empty inherited value produces only that directory. A nonempty first effective inherited value follows it after `:`; ordinary duplicate `PATH=` entries collapse to the one child value. This is test-process metadata only: build tools and every request that starts no test process retain their prior environment. #### Pinned Go evidence and classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - The `go test` command documentation states that `$GOROOT/bin` is placed at the beginning of the test process's `PATH`, so an executed test resolves the `go` command from the invoking toolchain ([`cmd/go/internal/test/test.go`, lines 87–94](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L87-L94)). - `(*runTestActor).Act` begins with `cfg.OrigEnv`, applies `base.AppendPATH`, then `base.AppendPWD`, and assigns that environment to each test command ([`cmd/go/internal/test/test.go`, lines 1661–1668](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1661-L1668)). `AppendPATH` appends `PATH=$GOROOT/bin` for an empty effective inherited value and `PATH=$GOROOT/bin:` otherwise ([`cmd/go/internal/base/env.go`, lines 29–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/base/env.go#L29-L45)). - `Cmd.environ` removes duplicate environment keys while preferring the later entry, making the appended value effective ([`os/exec/exec.go`, lines 1231–1265](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/exec/exec.go#L1231-L1265)). On the supported Unix model, initial environment lookup uses the first inherited occurrence ([`syscall/env_unix.go`, lines 20–44 and 66–84](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/syscall/env_unix.go#L20-L84)). - Official `test_goroot_PATH.txt` tests both an empty `PATH` and a nonempty directory containing no executable; the test must find the `go` executable in the current toolchain's `$GOROOT/bin` ([lines 1–41](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_goroot_PATH.txt#L1-L41)). Those source rules and official assertions are behavior directly implemented or asserted by pinned Go. Using the selected WW driver's sibling directory as the local toolchain-bin analogue is derived from that implementation: WW has no `GOROOT`, and that directory already supplies the driver's default compiler, assembler, linker, and package-test coordinator. Applying the rule to WW's raw single-file compatibility route is also derived; it is a local input extension, but it executes the same observable test and initialization code. Canonical absolute spelling is runtime metadata only and prevents a relative driver path from leaking the coordinator's later package cwd into `PATH`. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit considered all four permanent axes and selected only this test-runtime gap: - **Build:** pinned `runBuild` loads all roots and checks package errors before output/action construction ([`cmd/go/internal/work/build.go`, lines 459–478](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L478)); official `build_json.txt` distinguishes load errors from compiler failures ([lines 15–26 and 39–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_json.txt#L15-L45)). A direct missing-import probe made both WW stages exit `1` with the identical source diagnostic and no producer or public output. This candidate was aligned. - **Test:** direct Cstage and WWstage directory probes, each invoked with `PATH=/usr/bin:/bin`, both exited `0` while the test printed exactly that unchanged value. `/home/kimchi/src/ww/out/bin` was absent. These are directly measured pre-fix WW facts and establish the selected external difference. - **Package:** pinned `types2.(*Checker).initFiles` rejects package name `_` ([`cmd/compile/internal/types2/check.go`, lines 311–355](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/check.go#L311-L355)), with official anchors in [`internal/types/testdata/check/blank.go`](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/blank.go#L1-L5) and [`test/blank1.go`](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/blank1.go#L1-L10). Direct production, imported, and test-only probes were rejected identically by both WW stages. This candidate was aligned. - **Import:** pinned `unusedImports` requires every nonblank import binding to be used ([`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)); official `importdecl0` covers default, alias, dot, and blank forms ([lines 5–31](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L5-L31)). A direct unused default-import probe produced identical Cstage/WWstage diagnostics and no committed work. This candidate was aligned. The build, package, and import observations above are directly measured WW behavior; the linked rules are behavior directly implemented or asserted by pinned Go. The conclusion that this slice crosses those axes only when code in a successfully loaded test variant or initialized dependency observes `PATH` is derived from the pinned launch placement. #### Ownership, launch behavior, and preserved boundaries The environment is synthesized at the three true test-process launch owners: `internal/wwpackage.pkgstartrun` for directory products, Cstage `run_test_bin`, and WWstage `runsingletest` for raw single-file tests. Each uses the selected driver directory's canonical absolute spelling. The first effective uppercase inherited value is the suffix; absent and empty values have no suffix; ordinary uppercase duplicates are removed. For directory products, section 11.36 owns unrelated entries: a Go-like original-environment snapshot retains caller locale and temporary-directory values, case-distinct and nonempty malformed entries, and the final package `PWD`. Raw tests retain caller cwd, `PWD`, other environment entries, stdin, and split streams. The rule covers internal, external, and combined directory products; dependency initialization; filters and list mode; running retained tests; and raw single-file tests. It is independently materialized for each concurrent product. `ww build`, `ww run`, compiler/assembler/linker and generated-main commands, compile-only and assembly-only tests, no-test products, rejected requests, and later direct execution of a retained binary receive no test environment transformation. Loading, graph construction, compilation, assembly, linking, action keys, and artifact production are unchanged. A load, compile, or link failure starts no test process, so runtime `PATH` is inapplicable and the existing diagnostic precedence remains. A started test observes the new environment before normal success, assertion failure, signal, timeout, or interruption. Existing process groups, cancellation, output capture, and cleanup own those outcomes; the environment adds no global mutable state. A running retained request remains private build, private run, then guarded install, so any unsuccessful run publishes nothing and preserves prior bytes. Parallel products receive separate environment arrays and retain existing result isolation. Canonical physical driver directories do not become package, import, graph, action, artifact, symbol, `.wwi`, publication, or persistence identity. Compiled units, interfaces, archives, executables, modes, diagnostics, and public-output disposition are unchanged. No stored key or byte changed, so build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. The extended WW-native `directory_test_execution_working_directory` observer proves Cstage/WWstage equality for absent, empty, nonempty, and duplicate caller `PATH`; all directory test shapes and dependency initialization; filters, listing, raw single-file, and running retained tests; relative selected driver canonicalization; build/no-test/compile-only/rejection exclusions; unchanged compiler, assembler, and linker environments; concurrent products; runtime failure with prior retained-byte rollback; artifact-byte identity; and transaction, stage, workdir, and generated-file cleanup. Existing signal, timeout, interruption, concurrent-driver, and public-output transaction owners cover the unchanged mechanisms at those boundaries. ### 11.33 Implemented newline before directory test result trailers When a directory-owned test product has emitted a nonempty combined capture whose final byte is not newline, `ww test` now emits exactly one newline before its existing `ok` or run-status `FAIL` trailer. Empty and already newline-terminated captures gain no byte. The rule belongs only to the coordinator boundary between completed test-process output and its result trailer; it does not rewrite the capture or affect a route with no coordinator trailer. #### Pinned Go evidence and classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `(*runTestActor).Act` selects one output writer/buffer for a package test ([`cmd/go/internal/test/test.go`, lines 1436–1499](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1436-L1499)), then assigns that same writer to the test command's stdout and stderr and retains the resulting bytes as `out` ([lines 1661–1708](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1661-L1708)). - On success, a nonempty `out` without a trailing newline receives one before the `ok` record ([lines 1712–1732](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1712-L1732)). On failure with partial output, the same check inserts one before `FAIL` ([lines 1733–1769](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1733-L1769)). - Official `test_fail_newline.txt` asserts that buffered partial failure output and `FAIL` begin on different lines, and that buffered verbose partial success output and `ok` begin on different lines. It also records the deliberate streaming-mode exception ([lines 3–35](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_fail_newline.txt#L3-L35)). Those source rules and official script assertions are behavior directly implemented or asserted by pinned Go. Applying the buffered-package boundary to WW's directory-product capture is derived from that implementation: WW's manifest-free directory coordinator likewise owns the completed combined bytes and immediately appends a package result trailer. Excluding raw single-file tests and later manual execution of retained binaries is also derived from the pinned distinction: those WW routes have no coordinator-owned `ok` or `FAIL` trailer to separate. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit considered all four permanent axes and selected only this test-output gap: - **Go-like build:** pinned `(*ErrorReporter).errorUnresolved` gives an undeclared main function its dedicated link error ([`cmd/link/internal/ld/errors.go`, lines 29–65](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L65)). `TestUndefinedRelocErrors` directly requires build failure and that message ([`cmd/link/internal/ld/ld_test.go`, lines 19–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45)), using official `issue10978/main.go`, whose main function is absent ([lines 5–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/testdata/issue10978/main.go#L5-L27)). Direct Cstage and WWstage `ww build -o /dev/null` probes of a selected WW command package without `main` both exited `1`, produced the identical `w6l: undefined reference to 'main'` then `ww: w6l failed` diagnostics, and published nothing. This candidate was aligned. - **Go-like test:** a selected external `*_test.ww` initializer wrote exactly `partial-success` without newline and exited `0`. Both stages exited `0`, wrote no stderr, and emitted 72 stdout bytes beginning `partial-successok `. The corresponding initializer wrote exactly `partial-failure` to stderr and exited `7`; both commands exited `1`, wrote no coordinator stderr, and emitted 86 stdout bytes beginning `partial-failureFAIL `. Full Cstage and WWstage captures were byte-identical. These are directly measured pre-fix WW facts and establish the selected externally observable difference. - **Go-like package:** `MultiplePackageError` represents conflicting selected package clauses and formats the two declarations ([`go/build/build.go`, lines 538–548](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L548)); the scanner creates it when selected files disagree ([lines 930–967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L930-L967)), and `TestMultiplePackageImport` asserts the typed result and files ([`go/build/build_test.go`, lines 105–124](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L124)). Direct WW directories declaring `alpha` and `beta` were rejected before any producer by both stages with the same positioned conflict diagnostic. This candidate was aligned. - **Go-like import:** `loadImport` rejects a package declared `main` when it is imported from another directory ([`cmd/go/internal/load/pkg.go`, lines 787–805](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L787-L805)); official `import_main.txt` asserts the rule for builds and internal/external tests ([lines 3–35](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/import_main.txt#L3-L35)). Both WW stages rejected a direct dotted import of a package declared `main` with the identical `ww: package cmdpkg is a program, not an importable package` diagnostic. This candidate was aligned. The direct Go source and official-test statements above are behavior directly implemented or asserted by pinned Go. The WW command results are directly measured behavior. The conclusion that the selected change is a runtime presentation boundary, with no build, package, or import identity effect, is derived from the pinned placement after command completion and before the result record. #### Ownership, final behavior, and preserved boundaries `internal/wwpackage.pkgemitgroup` is the true owner because it alone has both the completed product-local combined capture and knowledge that an existing directory result trailer follows. It first emits the capture unchanged, then emits one separator only when the capture is nonempty and its last byte is not newline, then follows the established success or failure branch. The check is shared by Cstage and WWstage and is independent for every canonically ordered product, including internal, external, and combined variants; dependency initialization; filters and list mode; concurrent products; and the private run of a retained request. Empty output does not acquire a leading blank line, and output already ending in newline does not acquire a second one. A nonzero exit or signal retains its existing process classification and `FAIL` text; only a preceding partial line is terminated. Test-harness timeout and ordinary assertion output already end in newline and therefore remain byte-identical. A child that cannot start has no completed capture/trailer boundary in this function. Parent interruption, producer failure, and load, compile, assemble, archive, link, or install failure retain their existing diagnostics and precedence. Raw single-file tests and later direct execution of retained binaries have no package coordinator result trailer and retain their exact process bytes. Loading, graph construction, action construction and scheduling, compiler, assembler, archiver, linker, generated main, test executable, and retained artifact bytes are unchanged. The separator is emitted after the private process completes; it is not written into the capture, executable, interface, archive, work record, or public destination. Running retention remains private build, private run, then guarded install. Failed, signalled, interrupted, or unstartable runs still publish nothing and preserve prior retained bytes. Concurrent products retain separate capture files and canonical emission; there is no shared mutable newline state. Existing process-group cleanup, transaction rollback, temporary-root removal, and staged-file cleanup are unchanged. Physical source directories remain runtime/loader metadata only and do not become package, import, graph, action, artifact, symbol, `.wwi`, publication, or persistence identity. No persisted byte or key changes, so build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. The WW-native `directory_test_trailer_starts_on_new_line` observer proves both stages for unterminated stdout success, unterminated stderr failure, unterminated signal output, already terminated output, and empty output. It also covers concurrent products, a filter, list mode, running retained publication, retained executable byte identity, and the unchanged raw/manual routes; complete stdout and stderr from the concurrent Cstage and WWstage runs must match exactly. Existing package execution, timeout, interruption, transaction, persistence, byte-identity, and cleanup owners continue to prove the mechanisms this slice does not alter. ### 11.34 Implemented final `FAIL` for explicit ordinary test failures An ordinary `ww test` request with an explicit target now ends its ordered standard output with exactly one command-owned `FAIL\n` when test setup, build, or execution fails. The line follows every package result, including successful packages ordered after an earlier failure. It applies to one or many explicit directory, recursive, dotted-directory, or raw-file targets; filters and list mode; and the private execution of a retained test. It does not apply to bare implicit-current-directory `ww test`, `-c`, `-S`, `ww build`, command-line usage/shape or output preflight rejection, publication-only failure, capture-only failure, cleanup-only failure, allocation/systemic coordinator failure, or later direct execution of a retained binary. #### Pinned Go evidence and classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `runTest` reports setup errors, writes the per-package setup-failure result, and sets the command exit status ([`cmd/go/internal/test/test.go`, lines 1010–1061](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1010-L1061)). It then creates a root `go test` action owned by `printExitStatus`, orders all package print actions, and executes that root ([lines 1099–1124](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1099-L1124)). - `builderTest` constructs the ordinary build/run/clean/print chain and gives the run and print boundaries the failure handling needed to reach ordered output; its compile-only branch instead uses a dependency-sensitive nop print action ([lines 1133–1169 and 1185–1366](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1366)). - `(*runTestActor).Act` turns a dependency build failure into a package test result and sets exit status 1 ([lines 1436–1521](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1436-L1521)). Every non-nil execution error, including nonzero exit or abnormal/start failure, likewise sets the exit status and emits the package failure result ([lines 1644–1774](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1644-L1774)). - `builderCleanTest` and `builderPrintTest` put cleanup and captured package output before the root status action ([lines 2237–2259](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L2237-L2259)). `printExitStatus` then prints exactly `FAIL\n` when at least one package argument was explicit and the global exit status is nonzero ([lines 2262–2284](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L2262-L2284)). - Official `test_status.txt` requires a failing package, a later successful package, and a final standalone `FAIL\n` ([lines 3–6](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_status.txt#L3-L6)). Official `test_syntax_error_says_fail.txt` requires `FAIL` for an explicit test build/setup syntax failure ([lines 1–13](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_syntax_error_says_fail.txt#L1-L13)). - `testFlags` records explicit file operands in `pkgArgs` ([`cmd/go/internal/test/testflag.go`, lines 219–290](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/testflag.go#L219-L290)); `PackagesAndErrors` turns those files into the command-line package ([`cmd/go/internal/load/pkg.go`, lines 2895–2918](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2895-L2918)), which `GoFilesPackage` constructs ([lines 3244–3315](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L3244-L3315)). Those source rules and official assertions are behavior directly implemented or asserted by pinned Go. The single-explicit-package and raw-file cases are derived from `len(pkgArgs) != 0` and the explicit-file loading path. The bare implicit exclusion is derived from empty `pkgArgs`. The compile-only and publication-only exclusions are derived from their uncleared dependency failure preventing the root actor under the pinned work executor ([`cmd/go/internal/work/exec.go`, lines 134–205](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L134-L205)). #### Fresh four-axis audit and direct pre-fix measurements The bounded audit considered all four permanent axes and selected only this test-command status gap: - **Go-like build:** pinned unresolved-symbol handling and its undeclared-main case are owned by `(*ErrorReporter).errorUnresolved` ([`cmd/link/internal/ld/errors.go`, lines 29–65](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L65)), with official assertions in `TestUndefinedRelocErrors` ([`cmd/link/internal/ld/ld_test.go`, lines 19–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45)) and `issue10978/main.go` ([lines 5–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/testdata/issue10978/main.go#L5-L27)). Direct Cstage and WWstage no-main builds both exited 1 with identical linker diagnostics and no output. This candidate was aligned. - **Go-like test:** an explicit failing directory made both stages exit 1 with empty stderr and byte-identical 207-byte stdout (SHA-256 `3d0d44d5d9c4d4d95446382807ee092a611f19b43dc3013cf8df76f135cb5c46`), ending at its package failure rather than a standalone marker. A failing then successful `-j 2` request had byte-identical 384-byte stdout (SHA-256 `4623567924df78375fcca84ff797b7cb89d06d3fd5382704d8b9ebb79916b9d9`) ending at the successful `ok` result. A raw-file failure had byte-identical 121-byte stdout (SHA-256 `8db356ffc5b3a6d9df3308bfba8301329c5c07ce30c5ccd5cc5ee22a6c43331c`) ending at harness accounting. Explicit missing-import build failure likewise lacked the final marker. These directly measured pre-fix WW facts establish the selected external difference. Bare implicit and `-c` failures already omitted the marker and were aligned exclusions. - **Go-like package:** `MultiplePackageError` and package scanning implement conflicting selected declarations ([`go/build/build.go`, lines 538–548 and 931–967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L548)); `TestMultiplePackageImport` asserts the rule ([`go/build/build_test.go`, lines 105–133](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L133)). Both WW stages rejected an `alpha`/`beta` directory identically before tools. This candidate was aligned. - **Go-like import:** `unusedImports` and `errorUnusedPkg` implement the unused renamed-import diagnostic ([`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)); official `importdecl0` asserts ordinary and renamed forms ([lines 9–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L9-L27)). After normalizing only PID-bearing scratch roots, both WW stages produced the same unused-renamed-import diagnostic and no output. This candidate was aligned. The command results in that list are directly measured WW behavior; the linked source and tests are behavior directly implemented or asserted by pinned Go. The conclusion that only test presentation changes while build, package, and import identity remain fixed is behavior derived from the pinned action and final-status placement. #### Ownership, final behavior, and preserved boundaries The directory owner is `internal/wwpackage.packagecommand`: its private explicit-target bit affects only final status, and `pkgemitplan`/`pkgemitgroup` record attributable build/run failure while preserving canonical result order. After all package captures, package results, install attempts, and temporary-root cleanup, the coordinator emits one final line. Attributable setup/load rejection uses the same status helper. The two public drivers own the raw-file equivalent: they remember the producer or process result, finish their existing cleanup, then emit the line. A successful run followed only by install or cleanup failure does not acquire test-failure status. Loading and source selection, canonical package and import identity, graph nodes, action construction, scheduling, compiler/assembler/linker invocation, generated main, child argv/environment/cwd/stdin, capture bytes, package diagnostics, and diagnostic precedence are unchanged. Runtime nonzero exit, signal, timeout, and executable-start failure keep their existing classification; only the command status line follows. One command-global bit is isolated from every product-local capture, so parallel completion order cannot duplicate or reorder it. If the coordinator itself is interrupted before final emission no post-termination output is promised; an observed child interruption is an ordinary run failure. Artifact construction and bytes are unchanged. A failing running-retained test still preserves prior public bytes and creates no new executable; successful products in a mixed request retain their existing independent install results. Producer failure, publication rejection, transaction rollback, cleanup, and residue ownership are unchanged, and the marker creates no file. Physical directories and the private explicit-target signal do not enter package, import, graph, action, artifact, symbol, `.wwi`, publication, or persistence identity. No persisted byte or key changed, so build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. The WW-native `explicit_test_failure_has_final_status` observer covers both stages for single and concurrent failing/succeeding packages, filters, list mode, raw files, setup/build and runtime failure, success, bare implicit and compile-only exclusions, running retained rollback, artifact-byte equality, diagnostic equality, exact cardinality/order, and `.new`/transaction cleanup. Existing directory execution observers cover signals, timeouts, child cleanup, and canonical-order behavior with the new final line, while build-mode controls prove that the other command axis remains silent. ### 11.35 Implemented Go-like no-test-files package result A source-bearing directory test product with no selected `*_test.ww` file now reports exactly `? [no test files]\n` after ordinary production validation. It continues to create no test-support action, generated main, link, runnable, retained binary, captured runtime result, or process. The rule is shared by explicit directories, implicit current-directory selection, logical/dotted targets, recursive discovery, and compile-only or retained-output requests. Platform-ineligible test filenames do not prevent the result. A selected helper-only test file remains a real test product with an empty harness; the raw single-file compatibility route remains outside the directory-owned selected-test-file classification. #### Pinned Go evidence and fact classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `builderTest` detects `len(p.TestGoFiles)+len(p.XTestGoFiles) == 0`, keeps ordinary production as a dependency, constructs output-preparation and print actions, and creates no real test binary or run action ([`cmd/go/internal/test/test.go`, lines 1133–1169](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1133-L1169)). - `(*runTestActor).Act` owns that print action and writes exactly `? \t%s\t[no test files]\n` in the ordinary non-coverage case ([`cmd/go/internal/test/test.go`, lines 1524–1557, especially 1551–1552](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1524-L1557)). - Official `test_no_tests.txt` invokes `go test testnorun`, requires the `[no test files]` result, and gives production an initializer that panics if a test binary is linked and executed ([`cmd/go/testdata/script/test_no_tests.txt`, lines 1–14](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_no_tests.txt#L1-L14)). Those source rules and the script expectation are behavior directly implemented or asserted by pinned Go. That the ordinary case compiles production, prints the package result, and does not execute initialization is behavior derived from the pinned action graph. Applying the bracketed status to WW's established local package presentation is likewise derived: WW has no module import path, but its directory product already owns the corresponding selected-test-file decision and no-process action branch. This does not import Go's coverage behavior, module loader, cache, manifest, registry, or network resolution. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit considered all four permanent axes and selected only this test-result wording gap: - **Go-like build:** pinned unresolved-symbol handling and its special missing `main` case are implemented by `(*ErrorReporter).errorUnresolved` ([`cmd/link/internal/ld/errors.go`, lines 29–67](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L67)) and asserted by `TestUndefinedRelocErrors` ([`cmd/link/internal/ld/ld_test.go`, lines 19–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45)) using `issue10978/main.go` ([lines 5–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/testdata/issue10978/main.go#L5-L27)). Both WW stages rejected a selected `package main` without `fn main`, emitted identical 50-byte linker diagnostics, and created no output. This candidate was aligned. - **Go-like test:** a production directory with an aborting initializer and no test file made both stages exit 0 with empty stderr and byte-identical 55-byte stdout (SHA-256 `36adf30792e2900b60ec8cd02ba86e0387acebd41c4d9aab186af2c649ffe67c`): `? /tmp/ww-go1265-four-axis.Wq8d8H/notest [no tests]\n`. Bare implicit, logical `-I`, and `-c` forms produced the same bytes; `-c` created no binary. A platform-excluded test file produced the same old status class without observing its missing import or test body. These are directly measured pre-fix WW facts and establish the selected external difference. - **Go-like package:** `MultiplePackageError` and the package scan reject conflicting selected declarations ([`go/build/build.go`, lines 538–548 and 931–967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L548)); `TestMultiplePackageImport` asserts the file/name pairs ([`go/build/build_test.go`, lines 105–133](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L133)). Both WW stages rejected an `alpha`/`beta` production directory identically before tools. This candidate was aligned. - **Go-like import:** `unusedImports` and `errorUnusedPkg` implement unused ordinary and renamed-import diagnostics ([`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)); official `importdecl0` asserts both forms ([`internal/types/testdata/check/importdecl0/importdecl0a.go`, lines 9–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L9-L27)). After normalizing only PID-bearing scratch roots, both WW stages rejected an unused renamed dotted import with the same diagnostic and no output. This candidate was aligned. The command observations in that list are directly measured WW behavior. The linked source and testdata are behavior directly implemented or asserted by pinned Go. Selecting only the no-test-files presentation while keeping build, package, and import semantics fixed is behavior derived from the pinned action boundary and WW's already aligned no-process topology. #### Ownership, final behavior, and preserved boundaries `internal/wwpackage.pkgemitgroup` is the sole semantic owner of the directory package result. The loader still sets `g.notests` only after exact filename and platform eligibility have selected the source set. Product construction still compiles ordinary production and omits support/main/link/output/status actions; the scheduler still skips execution. The successful result literal changes only after that work succeeds. Loading, import, package, graph, compiler, assembler, archiver, linker, or publication failure therefore retains its prior diagnostic and precedence and cannot be hidden by a no-test-files result. Canonical dotted package/import identity, declared names, file-local import bindings, graph nodes and edges, action keys, physical-directory metadata, symbols, `.wwi`, source units, assembly, objects, archives, and executable bytes are unchanged. There is no new artifact or publication destination. `-c` and `-o` still omit a binary and do not create an otherwise-unused output hierarchy; prior caller state and persistent generations are preserved on every producer failure. Warm reuse and invalidation still concern production actions only. Concurrent products retain canonical ordered emission because the text remains inside the existing group emitter. Interruption before emission makes no new promise; the branch starts no child that can be signalled or timed out. Cleanup still removes only request-private plan state, creates no `.new` or `.install` stage, and leaves no test-process residue. Cstage and WWstage use the same coordinator owner and therefore emit byte-identical diagnostics and results. The WW-native `empty_and_invalid_package_classes` observer now requires the exact explicit and implicit result in both stages and uses an aborting production initializer to prove no process starts. Existing package observers cover logical and recursive selection, platform filtering, helper-only selected test files, compile-only/output omission, persistent cold/warm/invalidation behavior, large scheduling sets, failure rollback, stage parity, and artifact-byte identity. No persisted-byte contract changed: build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.36 Implemented original environment for directory test processes Every directory-owned test binary actually started by `ww test` now receives a Go-like snapshot of the caller environment instead of the package build plan's locale and temporary directory. On the supported Unix boundary, the snapshot keeps the first occurrence of every normal case-sensitive `key=value`, omits later normal duplicates and raw empty entries, and preserves nonempty malformed entries in order. The existing selected-toolchain `PATH` and package-directory `PWD` are then appended as the only test-command overrides. Caller `LC_ALL`, `TMPDIR`, empty-valued variables, case-distinct keys, and arbitrary variables therefore reach initialization and test code. #### Pinned Go evidence and fact classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `invoke` initializes `cfg.OrigEnv` from `toolchain.FilterEnv(os.Environ())` before command work ([`cmd/go/main.go`, lines 290–305](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/main.go#L290-L305)). `FilterEnv` removes only Go's internal toolchain-switch count variable ([`cmd/go/internal/toolchain/select.go`, lines 50–59 and 74–85](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/toolchain/select.go#L50-L85)); WW has no corresponding switch state. - `OrigEnv` is the startup environment and user binaries during `go test` use it instead of build-tool `CmdEnv` ([`cmd/go/internal/cfg/cfg.go`, lines 328–333](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/cfg/cfg.go#L328-L333)). - Unix `copyenv`, `Getenv`, and `Environ` retain the first occurrence of a normal case-sensitive key, clear later duplicates, omit cleared or empty entries from `Environ`, and leave nonempty malformed entries present ([`syscall/env_unix.go`, lines 20–50](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/syscall/env_unix.go#L20-L50), [66–84](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/syscall/env_unix.go#L66-L84), and [135–145](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/syscall/env_unix.go#L135-L145)). - `(*runTestActor).Act` clips `cfg.OrigEnv`, applies `AppendPATH` and `AppendPWD`, assigns the result to the package-directory command, and runs it ([`cmd/go/internal/test/test.go`, lines 1661–1697](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1661-L1697)). The two appenders are defined at [`cmd/go/internal/base/env.go`, lines 15–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/base/env.go#L15-L45), and explicit-command duplicate removal prefers their later `PATH` and `PWD` values ([`os/exec/exec.go`, lines 1231–1308](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/exec/exec.go#L1231-L1308)). - Official `test_env_term.txt` passes an explicitly empty caller `TERM` to a test and requires it to remain empty ([lines 1–14](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_env_term.txt#L1-L14)). `test_cache_inputs.txt` changes caller `TESTKEY` and its `TestLookupEnv` requires the arbitrary variable to be present ([lines 19–38](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_cache_inputs.txt#L19-L38) and [269–280](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_cache_inputs.txt#L269-L280)). Those source rules and official assertions are behavior directly implemented or asserted by pinned Go. That an ordinary caller `LC_ALL`, `TMPDIR`, case-distinct key, or other variable survives unchanged is behavior derived from the pinned pipeline: none is removed or replaced after the original snapshot. First-value normalization, malformed-entry retention, raw-empty omission, and the separation from build-tool `CmdEnv` are directly implemented by the cited source. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit considered all four permanent axes and selected only this test-runtime difference: - **Go-like build:** pinned unresolved relocation handling gives missing `main.main` its dedicated link failure ([`cmd/link/internal/ld/errors.go`, lines 45–65](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L45-L65)), asserted by `TestUndefinedRelocErrors` ([`cmd/link/internal/ld/ld_test.go`, lines 20–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L20-L45)). Both WW stages rejected a selected `package main` without `fn main`, emitted identical linker diagnostics, and created no output. This candidate was aligned. - **Go-like test:** a direct `execve` arranger supplied duplicate `LC_ALL`, `TMPDIR`, arbitrary, and `PWD` variables; one empty-valued normal variable; a case-distinct key; repeated nonempty malformed entries; and one raw empty entry. Both stages exited `0` with empty stderr and byte-identical stdout (SHA-256 `5b541239c8e9109c512b6ec7b8c59d4b18bf79391096fb14891d8de108786993`). The test reported caller arbitrary/empty/case-distinct values, but reported `LC_ALL` and `TMPDIR` as changed, two visible occurrences of the arbitrary normal key, and the raw empty entry still present. These are directly measured pre-fix WW facts and establish the selected difference. - **Go-like package:** `MultiplePackageError` and the directory scan reject conflicting selected declarations ([`go/build/build.go`, lines 538–549](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L549) and [939–967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L939-L967)); `TestMultiplePackageImport` plus official `testdata/multi` asserts the result ([`go/build/build_test.go`, lines 105–124](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L124)). Both WW stages rejected an `alpha`/`beta` source directory with byte-identical diagnostics and no output. This candidate was aligned. - **Go-like import:** `unusedImports` and `errorUnusedPkg` require a nonblank renamed import to be used ([`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)); official `importdecl0` asserts the alias case ([`internal/types/testdata/check/importdecl0/importdecl0a.go`, lines 5–31](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L5-L31)). Both WW stages rejected an unused local alias for dotted import `fmt` with the same semantic diagnostic and no output. This candidate was aligned. The command observations above are directly measured WW behavior. The linked rules are behavior directly implemented or asserted by pinned Go. Applying the original-environment pipeline at WW's directory-product launcher while leaving its raw single-file compatibility route intact is behavior derived from the pinned launch boundary and WW's local input model. #### Ownership, final behavior, and preserved boundaries `internal/wwpackage.runenv`, called only by `pkgstartrun`, is the semantic owner. It walks the coordinator's inherited vector in order, uses a bounded fallible open-addressed key table to retain the first normal case-sensitive occurrence, omits raw empty entries, retains nonempty malformed entries, and excludes exact uppercase `PATH` and `PWD`. It then appends the existing canonical selected driver `PATH` and `PWD=`. The table is freed before launch; `exec.start` deep-copies the command, after which the product-local vector and its two generated strings are freed. Concurrent products share no writable environment storage and the coordinator process is never mutated. `toolenv` remains the separate build-plan owner. Compiler, assembler, in-driver archiver, linker, support generation, generated-main construction, request scratch, cwd, argv, stdin, diagnostics, and failure precedence are unchanged; those tools still receive their established `LC_ALL=C` and request-private `TMPDIR`. The raw single-file route already preserved caller locale and temporary-directory values and remains outside this directory-owned normalization slice. A directly invoked retained binary still inherits its invoker's concrete environment without coordinator policy. Loading and platform source selection are unchanged. Production, internal-test, external-test, recompiled-for-test, support, and generated-main graph/action identity remain separate and unchanged. Canonical dotted package/import identity, declared names, file import bindings, physical-directory metadata, symbols, `.wwi`, source units, assembly, objects, archives, executables, modes, and artifact bytes do not contain the run environment. Imported or dependency initialization code observes the corrected values only inside the selected product process; no physical path or environment value becomes package, import, graph, action, artifact, publication, or persistence identity. `ww build`, `ww run`, directory `ww test -c` or `-S`, no-test products, and loading/compiler/linker rejection start no test process, allocate no run environment, and retain their prior diagnostics and outputs. A started test observes the corrected snapshot before success, assertion failure, signal, timeout, interruption, or child-created descendants. Those outcomes continue through the existing process-group, capture, ordered-result, cancellation, and cleanup owners. For a running retained request, private build and run still precede guarded installation: runtime failure publishes nothing and preserves prior bytes, while success installs the same private executable bytes. Producer failure, output guard failure, and cleanup-only failure retain their existing rollback and diagnostic precedence. Persistent work records and artifact invalidation are unchanged; test results are never cached. Environment-only changes perform the established warm final link and always run the private test, without changing committed action bytes. No `.new`, `.install`, `.wwtxn.*`, capture, result, process, or request scratch survives its existing cleanup boundary. This runtime-only metadata change alters no persisted-byte contract, so build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. The expanded WW-native `directory_test_execution_working_directory` observer proves both-stage equality for nonempty and empty-valued variables; caller `LC_ALL` and `TMPDIR`; first-wins normal duplicates; case-distinct and repeated malformed entries; raw-empty omission; package `PWD` and selected-toolchain `PATH`; production and test-only dependency initialization; internal, external, combined, and test-only products; filters/list/no-match; recursive/equivalent selection; serial/parallel scheduling; failure, signal, timeout, and child setup failure; retained success and rollback; cold/warm/data-only persistence; unchanged artifact and binary bytes; build/no-test/compile-only/rejection nonexecution; unchanged raw/direct compatibility; exact tool locale/TMPDIR; and stage, transaction, capture, and workdir cleanup. ### 11.37 Implemented empty list-mode output A valid directory-owned `ww test -list` request now emits one qualified test name per selected descriptor and emits no harness list bytes when its filters select zero tests. The test product still starts, package initialization still runs, the harness returns success without accounting, and the coordinator still emits the normal package `ok` result. Ordinary non-list execution with zero selected tests remains distinct: it keeps its discovered/selected/started/completed accounting and, as implemented later in section 11.39, uses the pinned no-tests warning and package-result suffix. #### Pinned Go evidence and fact classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `cmd/go` registers `-list` among the flags forwarded to the test binary ([`cmd/go/internal/test/testflag.go`, function `init`, lines 32–80](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/testflag.go#L32-L80)). - `testing.(*M).Run` calls `listTests`, sets exit code 0, and returns before the ordinary test execution and no-tests warning ([`testing/testing.go`, lines 2407–2411](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L2407-L2411) and [2440–2458](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L2440-L2458)). - `listTests` validates the pattern and prints only inside successful match branches. It has no zero-match output branch ([`testing/testing.go`, function `listTests`, lines 2509–2535](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L2509-L2535)). - `testShowPass` retains successful list output, while the successful run actor adds a no-tests suffix only if the captured bytes contain the ordinary no-tests warning ([`cmd/go/internal/test/test.go`, function `testShowPass`, lines 649–652](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L649-L652) and method `(*runTestActor).Act`, lines 1706–1732](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1706-L1732)). - Official `list_test_simple.txt` asserts that list mode emits the matching Test, Benchmark, and Example names ([`cmd/go/testdata/script/list_test_simple.txt`, lines 3–14](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/list_test_simple.txt#L3-L14)). Those source branches and official positive assertions are behavior directly implemented or asserted by pinned Go. That a zero-match `go test -list` run has no list payload, avoids the ordinary no-tests warning, and may still receive the command's normal successful package result is behavior derived from their composition. WW retains its local `-list` plus `-run`/`-filter` syntax; only the applicable selected-name and empty-result behavior is aligned. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit examined all four permanent axes before selecting this test runtime difference: - **Go-like build:** pinned `(*ErrorReporter).errorUnresolved` gives a missing `main.main` a dedicated failure ([`cmd/link/internal/ld/errors.go`, lines 29–67](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L67)), asserted by `TestUndefinedRelocErrors` and official `issue10978` ([`cmd/link/internal/ld/ld_test.go`, lines 19–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45), [`testdata/issue10978/main.go`, lines 5–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/testdata/issue10978/main.go#L5-L27)). Both WW stages rejected a selected command package without `fn main`, emitted zero stdout and the same 50 stderr bytes (SHA-256 `9ed4d7684412c6d2e615041902072c81e9e09acb3970246d89a2c8bdddd2fcfa`), and published no output. This audited applicable property was aligned. - **Go-like test:** for a directory containing one `visible` test, both stages ran `test -list -run no_such_test`, exited 0 with empty stderr, and emitted the same 78 stdout bytes (SHA-256 `d59638ab03a27803ca8e3fd884f341bbb1535ec9604fb69bdff1de4f608a8da0`): `[no matches]\n` followed by the normal package result. Positive list selection printed `list_nomatch.visible` once in both stages. This synthetic empty-result line was the selected difference. - **Go-like package:** pinned `MultiplePackageError` and directory scanning reject conflicting declarations ([`go/build/build.go`, lines 538–549](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L549) and [939–967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L939-L967)), asserted by `TestMultiplePackageImport` and official `testdata/multi` ([`go/build/build_test.go`, lines 105–133](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L133), [`testdata/multi/file.go`, lines 1–5](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/testdata/multi/file.go#L1-L5), and [`file_appengine.go`, lines 1–5](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/testdata/multi/file_appengine.go#L1-L5)). Both WW stages rejected an `alpha`/`beta` directory with zero stdout and the same 159 stderr bytes (SHA-256 `eaaa0c91f41b5d3deac4caf4299d5c7c650a1330be9b43edd090b8bfea906076`). This audited applicable property was aligned. - **Go-like import:** pinned `unusedImports` and `errorUnusedPkg` reject a nonblank unused alias ([`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)), asserted by official `importdecl0` ([`internal/types/testdata/check/importdecl0/importdecl0a.go`, lines 9–26](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L9-L26)). Both WW stages rejected an unused `spare` alias for dotted import `dep` with zero stdout and the same diagnostic after only private scratch-PID normalization (SHA-256 `a429b027e92d52de1c5ec581b1f45c860b0e85b459c3ac7347e2719900cec511`). This audited applicable property was aligned without changing dotted import identity. The command observations and byte hashes are directly measured WW behavior. The linked source branches and testdata assertions are behavior directly implemented or asserted by pinned Go. Applying the empty-list rule to WW's one local directory-owned test product while retaining its manifest-free input and filter syntax is behavior derived from that pinned execution boundary. Pre-fix `test -c` products were byte-identical between Cstage and WWstage: 112829 bytes, SHA-256 `d2994ef440d7ceb9be0a7caf53c90dd19d208e847e51ff41ecb89504f825c4c8`. Directly running either retained product with the same nonmatching list filter already emitted no stdout or stderr because it had no coordinator-supplied package prefix. Explicit raw-file requests with package options remained a separate rejected CLI shape in both stages. #### Ownership, final behavior, and preserved boundaries `lib/test.run` is the semantic owner. Its existing descriptor loop still qualifies, filters, and prints every positive list match in order; its list return now emits nothing extra when the selected count is zero. The package coordinator does not recognize or strip a magic line, so identical bytes written by package initialization or user code remain ordinary captured output. Loading and platform source selection are unchanged. Production, internal-test, external-test, recompiled-for-test, support, and generated-main nodes and actions remain unchanged. Exact dotted import identity, declared package names, aliases, variants, physical runtime directories, graph edges, initialization order, symbols, and publication names keep their existing roles. The product process and package initialization still run in list mode; no per-test child starts. Positive matching, option diagnostics and precedence, ordinary non-list no-match output, no-test-file results, and raw-file rejection were unchanged by this list-only slice; section 11.39 subsequently changes only the ordinary no-match warning and successful result annotation. The shared support implementation change legitimately changes its object, archive, and linked test-product bytes. Its exported signature and `.wwi` byte contract do not change. Existing content invalidation rebuilds the affected support/link actions; there is no test-result cache and no new graph identity. Running `-o` still executes the private product before guarded publication, and `-c`, destination safety, transaction rollback, prior-output preservation, and artifact modes are unchanged. Load, compile, assemble, archive, link, initialization, signal, timeout, interruption, child-start, publication, and cleanup failure paths retain their existing diagnostics and precedence. Parallel products keep independent processes, captures, environments, working directories, input descriptors, and ordered result slots. The changed runtime branch allocates and publishes no file, and existing cleanup remains responsible for `.new`, `.install`, `.wwtxn.*`, captures, process groups, and request scratch. The WW-native `list_mode_with_no_matches_emits_no_sentinel` observer proves both stages across concurrent combined and test-only products, package initialization, cold and warm persistent work, absence of list/accounting sentinels, positive deterministic selection, running `-o` retention, later direct execution, stage stdout/stderr equality, retained executable byte identity, and `.new` cleanup. The existing routing observer separately keeps the section-11.37 baseline for ordinary non-list reporting; section 11.39 supersedes that private marker while retaining the accounting. No persisted-byte contract changed: build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.38 Implemented declared-`main` function-kind semantics A package whose **declared package name** is `main` now rejects every package-scope non-function declaration named `main`. `let`, `const`, `def`, and `type` forms receive `cannot declare main - must be func` from either compiler checker and are not installed in package scope. The rule is deliberately narrower than Go's complete source signature rule: WW retains its established C/Hare-style program-entry ABI, including supported argument- and result-bearing function declarations. #### Pinned Go evidence and fact classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `types2.(*Checker).declarePkgObj` tests both identifier spelling `main` and `check.pkg.name == "main"`, emits `cannot declare main - must be func`, and returns without declaring the object ([`cmd/compile/internal/types2/resolver.go`, lines 90–110](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L90-L110)). The public checker implements the same condition and return ([`go/types/resolver.go`, method `(*Checker).declarePkgObj`, lines 103–124](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L103-L124)). - Official type-checker testdata rejects constant, type, and variable declarations named `main` in package `main` ([`internal/types/testdata/check/decls5.go`, lines 5–10](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/decls5.go#L5-L10)). The fixed-bug test also rejects `var main = func() {}`: a variable containing a function is still not a function declaration ([`test/fixedbugs/issue21256.go`, lines 1–9](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/fixedbugs/issue21256.go#L1-L9)). Those conditions, diagnostics, early returns, and testdata assertions are **behavior directly implemented or asserted by pinned Go**. That the semantic owner is package declaration checking; that a rejected object does not become the entry binding; and that declared package name rather than canonical path, path leaf, physical directory, or command selection owns the rule are **behavior derived from the pinned implementation**. Pinned Go separately requires a function `main` in package `main` to have no arguments or results ([`cmd/compile/internal/types2/resolver.go`, method `(*Checker).collectObjects`, lines 416–444](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L416-L444)), asserted by official `mainsig.go` ([lines 7–13](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/mainsig.go#L7-L13)). That is also **behavior directly implemented or asserted by pinned Go**, but it does not honestly apply to WW's source ABI. Both baseline WW stages accepted `fn main(x: i32) void` and `fn main() i32`, produced byte-identical executables, and ran them successfully; WW's own self-hosted command tools use `main(argc: i32, argv: **u8) i32`. Those observations are **directly measured WW behavior**. Preserving those function forms while applying the independent declaration-kind requirement is **behavior derived from the pinned implementation within WW's applicable model boundary**. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit examined all four permanent axes before this package slice was selected: - **Go-like build:** pinned `(*ErrorReporter).errorUnresolved` gives missing `main.main` a dedicated error ([`cmd/link/internal/ld/errors.go`, lines 29–67](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L67)), asserted by `TestUndefinedRelocErrors` ([`cmd/link/internal/ld/ld_test.go`, lines 19–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45)) and official `testdata/issue10978/main.go` lines 5–27. Both WW stages rejected a selected `main` package with no entry, emitted empty stdout and the same 50 stderr bytes (SHA-256 `9ed4d7684412c6d2e615041902072c81e9e09acb3970246d89a2c8bdddd2fcfa`), and published nothing. This applicable control was aligned. - **Go-like test:** pinned `isTestFunc` and `checkTestFunc` define and reject a wrong test function shape ([`cmd/go/internal/load/test.go`, lines 555–579 and 775–787](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L555-L579)), with the official wrong-signature script anchor at [`cmd/go/testdata/script/test_main.txt`, lines 11–13 and 30–40](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_main.txt#L11-L13). Both WW stages rejected `@test fn bad(x: i32) void` before execution, emitted the same semantic diagnostic, no accounting, and final `FAIL\n` stdout (SHA-256 `4f8e9e45f8a9e1843b81eaf3bdf52a6b778d415d23bf985774a9d34a43f69bd5`). This applicable control was aligned. - **Go-like package:** baseline Cstage accepted `let main`, `const main`, and `def main`, published mode-0755 executables, and those executables exited 139 with empty output. The `let`/`const` executable SHA-256 was `edd3bad62be69701a373aa0567972bfb976690b0332b8c117891125254fc85b5`; the `def` executable SHA-256 was `9e56d6710395b287e18e85187eee86d846927c6f3ea91216858c6026f38ebdff`. Cstage `type main` and every WWstage non-function form instead reached the linker's missing-`main` failure. Neither stage emitted the pinned package diagnostic. Both stages accepted a directory command package containing `let main` plus a valid internal test, ran it, and reported package `ok` with byte-identical 178-byte stdout (SHA-256 `a6e165fb558be62932e217ccd1d3175348f7490489bca8e9828872e28c01236f`). This was the selected difference. - **Go-like import:** pinned `unusedImports` and `errorUnusedPkg` reject a nonblank unused alias ([`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)), asserted by official `importdecl0a.go` lines 9–27. Both WW stages rejected unused `import spare audit.dep;`, emitted empty stdout, and reported `"audit.dep" imported as spare and not used`. This applicable control was aligned. The WW command results, output lengths, hashes, exit statuses, and runtime signals are **directly measured WW behavior**. The linked source and testdata facts are **behavior directly implemented or asserted by pinned Go**. Selecting the declaration-kind rule while excluding the incompatible function-signature rule is **behavior derived from the pinned implementation**. As an identity control, both stages built `package utility; export let main: i32 = 7` as byte-identical 924-byte archives (SHA-256 `10382e7812229d73c4acefdf8988a13372b6eb7a2981559b3adade524ed5a929`). That is **directly measured WW behavior** and pins the required non-effect for non-`main` declared packages. #### Ownership, final behavior, and preserved boundaries `reject_nonfunction_main_decls` in `cmd/wcc/check.c` and its self-hosted twin `rejectnonfunctionmaindecls` in `selfhost/cmd/wcc/check.ww` are the semantic owners. They run after parsing but before qualified-use discovery and package name installation. Each walks selected top-level declarations, tests the declaration-carried `pkgname`, reports the pinned diagnostic, and removes only the rejected node from subsequent package-scope checking. This mirrors the pinned resolver's return-before-declare behavior. No driver mode, entry flag, canonical action key, directory classification, or linker-symbol heuristic is consulted. Direct post-fix calls to `w6c` and `w6c_ww` on the same invalid source now exit 1 with empty stdout, no assembly output, and byte-identical 102-byte stderr (SHA-256 `39001ed88e2ab8b7675fcc51b4b794cf8ebc2a803e1f05de45d7d0ba1cd98a38`) ending in `cannot declare main - must be func`. Directory builds of all four forms fail through `ww: w6c failed for ...`, never reach `w6a` or `w6l`, publish no output, and give byte-identical Cstage/WWstage diagnostics when the owned output path is the same. Directory tests emit only the command-owned final `FAIL\n` on stdout, report build failure on stderr, and emit no test body, accounting, or package `ok` result. Loading and Go-platform source eligibility are unchanged. Production and test source selection still determines which declarations reach the checker; an excluded source has no effect. Declared package name remains independent from canonical dotted identity, aliases, path leaf, filename, physical directory, requested root, output name, linker order, and artifact/storage locator. A dependency physically and canonically ending in `main` but declared `utility` continues to export `main`, bind through its declared qualifier, and produce stage-byte-identical `.unit.ww`, `.wwi`, assembly, object, archive, and command executable bytes. Valid `main(argc, argv) i32` and `main() i32` commands remain accepted and byte-identical between stages. Graph construction and action identities are unchanged for valid programs. An invalid selected command or command-test variant reaches its normal compiler action and fails there; assembler, archiver, linker, runtime, generated test execution, and publication do not become alternative semantic owners. An ordinary import of a declared-`main` package is still rejected earlier by the loader as `ww: package PATH is a program, not an importable package`, even when that command also contains the malformed declaration. This preserves import diagnostic precedence and the toolchain-owned external-test exception. Cold rejection creates no output or retained scratch. Warm rejection after a successful command preserves the complete committed owner unit, interface, assembly, object, archive, init unit/assembly/object, tool vouchers, workdir stamp, and public executable byte for byte. It installs no staged generation; exact source restoration reuses the committed action and reproduces the prior binary. There is no test-result cache and no new reuse key. Producer failure, rollback, existing-output preservation, concurrent action isolation, interruption, process cleanup, and transaction cleanup continue through their existing owners; the checker adds no process, descriptor, mutable global state, or cleanup path. No active `.new`, `.install`, `.wwtxn.*`, adjacent rejection scratch, test child, or capture survives the tested failure boundaries. The WW-native `nonfunction_main_declarations_reject` observer proves all four non-function kinds, exact direct-compiler stage parity, cold build rejection, directory-test nonexecution, declared-name/dotted-import/physical-leaf separation, supported entry ABI preservation, valid artifact-byte parity, command-import precedence, complete warm work/publication rollback, restored reuse, and residue absence. Existing interruption and concurrent-transaction observers remain the owners of those unchanged mechanisms; this declaration check introduces no independently interruptible or shared state. No valid persisted-byte contract changed. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.39 Implemented ordinary zero-match test results An ordinary successful directory `ww test` whose valid `-run`/`-filter` selection starts no registered test now uses Go's externally visible no-tests protocol. The shared test runtime writes exactly `testing: warning: no tests to run\n` through standard error, retains WW's discovered/selected/started/completed accounting, and returns success. The directory coordinator recognizes that exact line at capture byte zero or after a newline and appends ` [no tests to run]` to the corresponding successful package `ok` result. WW's former `[no matches]` sentinel is no longer emitted. This is deliberately distinct from the completed list-mode rule: list mode returns before the warning/accounting branch and retains an unsuffixed package result. A source-bearing directory without test files also retains its separate `? [no test files]` result and starts no runtime product. #### Pinned Go evidence and fact classification The sole semantic authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `testing.(*M).Run` returns directly from list mode at lines 2407–2411. In ordinary execution it gathers whether tests, examples, or fuzz targets ran, writes exactly `testing: warning: no tests to run` to stderr when none did, and keeps the outcome successful when no independent failure occurred ([`testing/testing.go`, lines 2432–2485](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L2432-L2485)). - `cmd/go` defines the line-delimited `noTestsToRun` marker ([`cmd/go/internal/test/test.go`, line 1385](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1385)) and, after a successful test process, recognizes it at capture byte zero or after a newline and appends ` [no tests to run]` to the package result ([method `(*runTestActor).Act`, lines 1706–1732](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1706-L1732)). - Official script/testdata `test_match_no_tests.txt` runs one registered test through a nonmatching filter and asserts the suffixed successful package result ([lines 1–11](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_match_no_tests.txt#L1-L11)). - Official precedence script/testdata `test_match_no_tests_build_failure.txt` asserts that a build failure under a nonmatching filter produces `FAIL` and does not acquire a successful no-tests result ([lines 1–18](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_match_no_tests_build_failure.txt#L1-L18)). Those branches, exact bytes, success conditions, delimiter checks, result suffix, and script assertions are **behavior directly implemented or asserted by pinned Go**. That the runtime owns whether a test ran, the coordinator owns the package-result annotation, a build failure precedes both, and an arbitrary mid-line substring is not the marker are **behavior derived from the pinned implementation**. WW retains its fnmatch-based local `-run`/`-filter` language rather than adopting Go regular expressions. WW also has an established always-visible harness report rather than Go's quiet/`-v` presentation switch, so this slice does not suppress every successful product capture or replace WW accounting with Go's `PASS` line. Within that honest local presentation boundary, the zero-execution warning, stream owner, success classification, marker delimiter, and package annotation apply directly. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit examined all four permanent axes before selecting this test runtime/coordinator difference. Commands used Cstage `out/bin/ww` and WWstage `out/bin/ww_ww` against identical sources: - **Go-like build:** pinned linker method `(*ErrorReporter).errorUnresolved` gives missing `main.main` a dedicated failure ([`cmd/link/internal/ld/errors.go`, lines 29–67](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L67)), asserted by `TestUndefinedRelocErrors` and official `issue10978` ([`cmd/link/internal/ld/ld_test.go`, lines 19–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45), [`testdata/issue10978/main.go`, lines 5–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/testdata/issue10978/main.go#L5-L27)). Both WW stages rejected a declared-main package with no entry, emitted empty stdout and the same 50 stderr bytes (SHA-256 `9ed4d7684412c6d2e615041902072c81e9e09acb3970246d89a2c8bdddd2fcfa`), and published nothing. This applicable build property was aligned. - **Go-like test:** with one registered test, both stages exited 0 for `test -run no-such-*`, emitted empty stderr, and emitted the same 120 stdout bytes (SHA-256 `ca12f88ebf1f94d3a2ca63ed1bc1e9b5a4811a660df3af4e70c7b9624ef97c40`): `[no matches]`, zero-selection accounting, and an unsuffixed package `ok`. This private marker and missing result annotation were the selected gap. Empty list selection and positive ordinary selection were already aligned controls and stayed outside the changed branch. - **Go-like package:** pinned `MultiplePackageError` and directory scanning reject conflicting declarations ([`go/build/build.go`, lines 538–549](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L549) and [939–967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L939-L967)), asserted by `TestMultiplePackageImport` and official `testdata/multi` ([`go/build/build_test.go`, lines 105–133](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L133)). Both WW stages rejected one `first`/`second` directory with empty stdout and byte-identical 161-byte stderr (SHA-256 `a2d95681b8a97d55c26367084cd294632fa015882d1aa53b0df63f24bcf24ced`). This applicable package property was aligned. - **Go-like import:** pinned `unusedImports` and `errorUnusedPkg` reject every nonblank unused import ([`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)), asserted by official `importdecl0a.go` ([lines 9–26](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L9-L26)). Both stages rejected an unused dotted `fmt` import with empty stdout and the same semantic diagnostic; raw stderr differed only in the deliberately stage-named private output path. This applicable import property was aligned. The WW statuses, streams, lengths, hashes, and diagnostics are **directly measured WW behavior**. The linked official implementation and testdata are **behavior directly implemented or asserted by pinned Go**. Applying the runtime/coordinator split without changing WW's filter syntax or harness report is **behavior derived from the pinned implementation**. #### Ownership, final behavior, and preserved boundaries `lib/test/run.ww` is the runtime owner. Its existing `selected == 0` branch now writes the pinned warning through the same EINTR-safe fd writer used elsewhere, targeting stderr, then writes the unchanged accounting to stdout and returns 0. Its earlier list return is untouched. A directly invoked retained binary therefore exposes the warning on stderr and accounting on stdout. `internal/wwpackage/package.ww` is the directory result owner. It already gives each product one combined stdout/stderr capture and emits that capture in canonical group order. Its new predicate accepts only the exact warning at byte zero or following `\n`; after `pkgrunok` succeeds, `pkgemitgroup` appends the suffix to the result it already owns. Text embedded mid-line in a running test does not match. A failed, signalled, timed-out, interrupted, or unstartable test does not reach the successful result. A producer failure never starts the runtime and cannot synthesize the warning or suffix. Both selected driver stages compile the same `lib/test` code into test products and delegate directory execution to the same WW-native coordinator, so no C-only or self-host-only semantic fork was introduced. Direct post-fix probes through both stages exited 0, emitted empty coordinator stderr, and emitted the same 159 stdout bytes (SHA-256 `a67242ab79b9bd9bca1a32073c1fccbb9aa4fa9d8ad52ced667b25c54dc1be08`): the warning, unchanged accounting, and suffixed package result. Loading and Go-platform source selection are unchanged. Production, internal-test, external-test, recompiled-for-test, support, and generated-main graph nodes and actions are unchanged. Compilers, assemblers, archivers, and linkers retain their diagnostics and scheduling. The support implementation change legitimately changes its object/archive and linked test-product bytes, but its exported signature and `.wwi` contract do not change; valid Cstage and WWstage retained products remain byte-identical. Declared package names and canonical dotted import identities remain separate. The coordinator annotates an already-owned result; it derives no identity from the warning, alias, declared name, path leaf, filename, physical directory, output path, artifact name, or linker order. Physical directories remain test cwd and result-label metadata only, never package/import/graph/action/artifact/ symbol/`.wwi`/publication/persistence identity. Cold and warm persistent work produce identical result bytes and still run the test product because there is no test-result cache. A successful retained run publishes the privately tested executable through the existing guarded install. A later producer failure preserves prior public bytes, and restored valid reuse reproduces the same warning/suffix without rewriting an identical executable. Publication rejection, rollback, existing-output preservation, concurrency, interruption, process-group cancellation, capture separation, final `FAIL`, and cleanup remain with their existing owners. No active `.new`, `.install`, `.wwtxn.*`, adjacent `.sepwork`, process, or capture residue is introduced. The WW-native `ordinary_no_match_uses_go_warning_and_result_suffix` observer proves both stages; cold/warm reuse; concurrent reverse-requested packages and ordered per-product markers; exact mid-line rejection; positive, list, and no-test-files controls; retained publication and direct stderr ownership; producer-failure precedence; cold/repeated failure; prior-output preservation; restored reuse; normalized diagnostic parity; retained executable byte identity; and transaction/output-scratch cleanup. Existing signal, timeout, interruption, and process-group observers continue to prove those unchanged mechanisms. This is runtime/coordinator presentation, not a persisted-byte contract. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.40 Implemented current-directory default build names An empty `ww build` package list selects the current directory just as an explicit `.`, `./`, or equivalent sequence of single-dot components does. For one command package and no explicit `-o`, the public executable is now named by the selected directory's final component. The selector is loading syntax; it is not the literal output pathname. Thus a command built while the current directory is `tool` publishes `tool`, not `.`, and cold private build artifacts use `tool.sepwork`, not `..sepwork`. A non-main current-directory package uses the same corrected cold scratch stem, but still has no link or public installation action. An explicit `-o`, exact `-o /dev/null`, an ordinary non-current directory operand, and a contextual dotted package request keep their established output rules. #### Pinned Go evidence and fact classification The sole semantic authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `search.CleanPatterns` turns an empty package-pattern list into exactly `.`; `ImportPathsQuiet` then treats that local pattern as a directory selection ([`cmd/go/internal/search/search.go`, lines 441–480](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/search/search.go#L441-L480)). - `work.runBuild` loads packages and checks load errors before output planning. With exactly one loaded `main` package and no `-o`, it selects `DefaultExecName` ([`cmd/go/internal/work/build.go`, lines 459–478](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L478)). - `load.(*Package).exeFromImportPath` takes the final loaded import-path element, while `DefaultExecName` uses a source basename only for a command-line-files package ([`cmd/go/internal/load/pkg.go`, lines 1727–1769](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L1727-L1769)). - Official command testdata distinguishes module naming from the manifest-free GOPATH case and requires bare `go build` to create the directory-named `src` executable ([`clean_binary.txt`, lines 15–28](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/clean_binary.txt#L15-L28)). A second manifest-free script changes to `m`, runs bare `go build`, and requires executable `m` ([`gccgo_m.txt`, lines 4–14](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/gccgo_m.txt#L4-L14)); `build_static.txt` likewise builds and executes the default `hello` ([lines 11–14](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_static.txt#L11-L14)). Those selection, loading, default-name branches and script assertions are **behavior directly implemented or asserted by pinned Go**. WW has no module or manifest identity for a literal root, so using the selected local directory leaf as its already-specified presentation fallback is **behavior derived from the pinned implementation**. The directory remains loader metadata and does not become canonical package or import identity. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit examined every permanent axis before choosing this build presentation difference. Both public stages were measured at the same source paths: - **Go-like build:** multi-command directory selection without `-o` was already aligned. For a valid command in directory `a`, however, bare `build`, `build .`, and `build ./` each exited 1 in both stages with empty stdout and the same 55 stderr bytes (SHA-256 `2e8030a9eeb7187fbc1cb4ee9d794c352f1c31c92c884f8ae09a57e39bfe86db`): `ww: build output "." already exists and is a directory`. Explicit `-o` succeeded and produced byte-identical runnable binaries, proving that only default presentation was wrong. This was the selected gap. - **Go-like test:** an ordinary valid zero-match directory run exited 0 in both stages with identical warning, accounting, and `[no tests to run]` result bytes. The selected build branch does not enter test product naming, filtering, capture, execution, result annotation, or retained test output. - **Go-like package:** a directory containing two selected declared package names was rejected in both stages with identical diagnostics. The selected change occurs after package loading and does not alter source eligibility, declaration checks, package kind, graph nodes, or actions. - **Go-like import:** a dotted `cyclea -> cycleb -> cyclea` graph was rejected in both stages with identical cycle diagnostics. The selected change does not alter spelling, search, visibility, resolution, canonical identity, or graph edges. The pre-fix statuses, streams, hashes, diagnostics, artifacts, and runtime results are **directly measured WW behavior**. The cited implementation and testdata are **behavior directly implemented or asserted by pinned Go**. The cross-axis non-effects follow from the bounded post-load output branch and are **behavior derived from the pinned implementation**. #### Ownership, final behavior, and preserved boundaries `cmd/ww.do_build` and `selfhost/cmd/ww.dobuild` are semantic twins and the sole owners of this rule. Their current-directory predicate accepts only relative paths whose components are all exactly `.`. Only in that branch do they canonicalize the selected directory and take its final component for output and cold scratch presentation. Ordinary literal directory operands retain their lexical leaf, and contextual roots retain their dotted identity leaf. Direct post-fix probes through both stages show that bare, dot, and dot-slash builds exit 0 with empty stdout/stderr, publish mode-executable binaries named `a`, and produce `a.sepwork` with no `..sepwork`. All six binaries are byte-identical (SHA-256 `866c1eb875dad271d37572f43fb9d9b0eb6a2344d2e61646e655bb09f7909bf6`). Their unit, interface, assembly, object, archive, and init artifacts are also byte-identical between stages and spellings. Current-directory library builds still publish nothing and link nothing; their unit, interface, assembly, object, and archive bytes remain stage-identical under `libcurrent.sepwork`. Loading and source selection precede this branch. A missing dotted import therefore retains its byte-identical diagnostic and creates neither output nor scratch. Graph and action construction, compiler/assembler/archiver/linker semantics, runtime behavior, and artifact content are unchanged. A genuine directory occupying the derived output still rejects before tools and names the derived leaf in its diagnostic. Cold and warm persistent builds retain their existing keys and reuse rules. A source invalidation reruns producers; an injected compiler failure preserves the prior executable and committed persistent generation, publishes no stage, and leaves no `.new`, `.install`, or `.wwtxn.*` residue. Restoring producer success installs the changed executable. Existing concurrency, interruption, process-group, rollback, publication, and cleanup owners gain no shared state or new process path. The WW-native `current_directory_build_default_output` observer proves both stages, all three current-directory spellings, executable mode/runtime/byte parity, explicit and null output controls, non-main non-publication, corrected cold scratch, missing-import precedence, cold/warm reuse, invalidation, producer-failure rollback, prior-output preservation, genuine collision, and residue absence. Existing package/import graph, byte-identity, concurrent transaction, and interruption observers remain authoritative for mechanisms this presentation rule does not change. No persisted-byte contract changed. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.41 Implemented source-file import-section ordering Every eligible WW source now has one contiguous import section immediately after its package clause. Once an ordinary top-level declaration begins, the first `import` in a later section is rejected as `imports must appear before other declarations`. The parser continues for recovery: consecutive imports in that late section do not repeat the ordering diagnostic, while another ordinary declaration followed by another import starts a separately diagnosed late section. This is a source-file syntax rule, not a new import form. Existing unquoted dotted default, explicit-alias, and blank imports are unchanged. Existing aggregate module/reset boundaries and each constituent package clause begin a new source section. The boundary bookkeeping remains parser metadata rather than package, import, graph, action, artifact, symbol, `.wwi`, publication, or persistence identity. #### Pinned Go evidence and fact classification The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `syntax.(*parser).fileOrNil` states the source-file grammar as a package clause, zero or more imports, and then zero or more top-level declarations. Its recovery loop accepts a later import only to continue parsing and emits exactly `imports must appear before other declarations` when the preceding declaration was not an import ([`cmd/compile/internal/syntax/parser.go`, lines 397–428](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/parser.go#L397-L428)). - The public parser first consumes the initial import section, then applies the same predecessor check while parsing the rest of the file ([`go/parser/parser.go`, method `(*parser).parseFile`, lines 2887–2923](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/parser/parser.go#L2887-L2923)). - Official types testdata requires one diagnostic for a late import followed by contiguous imports, then another diagnostic when an ordinary declaration separates a second late section ([`internal/types/testdata/fixedbugs/issue43190.go`, lines 5–30](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/fixedbugs/issue43190.go#L5-L30)). Those grammar branches, diagnostic text, error-recovery behavior, and testdata assertions are **behavior directly implemented or asserted by pinned Go**. That the state belongs to one source parser, resets at WW's existing aggregate source boundaries, and must reject before import-graph construction is **behavior derived from the pinned implementation**. The rule honestly applies to WW's model because it orders declaration classes WW already implements. It requires no quoted, grouped, dot, or generalized import syntax; module or manifest identity; registry, lock, cache, database, CAS, or network resolution; or source-level build expression. #### Fresh four-axis audit and direct pre-fix measurements The bounded audit examined all four permanent axes against the pinned checkout before selecting this import difference: - **Go-like build:** pinned linker method `(*ErrorReporter).errorUnresolved` gives unresolved `main.main` a dedicated error ([`cmd/link/internal/ld/errors.go`, lines 29–67](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/errors.go#L29-L67)), asserted by `TestUndefinedRelocErrors` and its source fixture ([`cmd/link/internal/ld/ld_test.go`, lines 19–45](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/ld_test.go#L19-L45), [`testdata/issue10978/main.go`, lines 5–27](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/link/internal/ld/testdata/issue10978/main.go#L5-L27)). Both WW stages rejected a selected declared-`main` package without an entry, using empty stdout and the same linker/driver diagnostics. This applicable control was aligned. - **Go-like test:** pinned `testFlags` explicitly permits known test flags before and after the package list and implements the transition between package operands and flags ([`cmd/go/internal/test/testflag.go`, lines 219–345](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/testflag.go#L219-L345)); official `test_flag.txt` asserts both placements ([lines 1–4](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_flag.txt#L1-L4)). In both WW stages, `-run selected` before or after a directory operand ran exactly the same one of two registered tests and produced identical output. This applicable control was aligned for WW's supported option set. - **Go-like package:** pinned `MultiplePackageError` and directory scanning reject two eligible declarations with different package names ([`go/build/build.go`, lines 538–549](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L538-L549) and [lines 939–967](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L939-L967)), asserted by `TestMultiplePackageImport` ([`go/build/build_test.go`, lines 105–133](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build_test.go#L105-L133)). Both WW stages rejected a `first`/`second` directory before tools with the identical positioned diagnostic. This applicable control was aligned. - **Go-like import:** a command source declared a helper, then imported `audit.dep`, then used that package from `main`. Both WW stages exited 0, emitted empty build output, produced byte-identical executables (SHA-256 `f28892147ab0ae283dff5ceea7114dbc81142ed48cb9088ee7fb8294a5ce44cd`), and those executables exited 42. Corresponding owner unit, interface, assembly, object, archive, and initializer bytes were stage-identical. A same-package test source with the same late-import shape ran successfully in both stages with identical 251-byte stdout (SHA-256 `3c42fa9840f485fb21b5b5318a13b89abfe29e94b530db00779262368f4fbeba`) and empty stderr. This acceptance was the selected difference. The WW statuses, streams, runtime exits, and artifact hashes are **directly measured WW behavior**. The cited implementation and testdata facts are **behavior directly implemented or asserted by pinned Go**. Applying their per-file ordering state to WW's existing dotted declarations is **behavior derived from the pinned implementation**. #### Ownership and final four-axis behavior `parseimports` and `parsefile` in `cmd/wcc/parse.c`, with their semantic twins in `lib/ww/syntax/parse.ww`, are the only production owners. Each keeps one parser-local `previmport` bit. A normal import following a non-import reports the pinned diagnostic, then sets the bit so adjacent imports remain one recovery section. Any ordinary declaration clears it. The existing module-path, module-reset, and package-clause boundaries set it for a new source section. The imports-only pass is used by public driver loading and therefore rejects a selected or imported late source before graph and producer construction. The full parser independently gives direct `w6c`/`w6c_ww` input and aggregate units the same rule. The only tracked compatibility fixture that deliberately put a declaration before its import was reordered; it still proves file-scoped import binding and declaration installation order with byte-identical Cstage/WWstage artifacts, without asserting the rejected syntax. - **Go-like build:** selected and imported late sources now fail during parser loading, before compiler, assembler, archiver, linker, output planning side effects, or runtime. Missing-target resolution does not replace the earlier syntax error. Valid import-first commands still build, publish, and run. - **Go-like test:** late imports in production, same-package test, external-test, and test-only sources fail before variant actions, generated main, test binary, runtime, accounting, or retained publication. The directory command emits its existing attributable final `FAIL\n`. A valid import-first test retains and runs normally. - **Go-like package:** source eligibility and package-clause classification remain earlier owners. Wrong-platform sources produce no ordering error; selected package-name conflicts retain their coordinator diagnostic. Declared names and command/test family classification are unchanged. - **Go-like import:** a file can no longer introduce a qualifier or side-effect edge after ordinary declarations. Valid imports retain their exact source spelling, declared-name qualifier, file scope, contextual/vendor resolution, canonical identity, visibility checks, cycle checks, and initialization edges. Direct post-fix `w6c` and `w6c_ww`, and public `ww build`/`ww_ww build`, reject the measured source with empty stdout and byte-identical 149-byte stderr (SHA-256 `791ac87ab0aa2c91228f863ae80a8815aa83edf78c4996c5f11191193e3e4240`). The diagnostic points to the late import at line 7, column 1. Directory tests emit byte-identical `FAIL\n` stdout (SHA-256 `4f8e9e45f8a9e1843b81eaf3bdf52a6b778d415d23bf985774a9d34a43f69bd5`) and byte-identical 314-byte stderr (SHA-256 `82ec52b26eaff053f475ce0773b7aee902e734cd87dc100848aee3772063f5b1`), with no test body or accounting. A direct three-import recovery probe emits exactly two stage-identical ordering diagnostics: one for the first of two contiguous late imports and one after the intervening declaration. Loading and fixed-target filename selection otherwise do not change. An excluded `_windows.ww` or `_windows_test.ww` file contributes no parse, package, import, graph, action, artifact, diagnostic, or invalidation state. For valid files, graph nodes, action dependencies and scheduling, compiler and linker arguments, initialization, runtime behavior, result ordering, and publication remain unchanged. A package canonically named `domain.dep` may still declare `renamed`; its importer uses `renamed.Name`, and its unit/export remain owned by `domain.dep`. Cold rejection creates no work artifact, output, capture, or adjacent scratch. A warm source reordered into the invalid form preserves the complete committed unit/interface/assembly/object/archive/initializer generation, tool vouchers, stamp, and public executable byte for byte. Exact restoration reuses the committed producers and republishes the same executable. Because rejection occurs before a producer or test child, producer failure, runtime failure, signals, timeout, interruption, and process-group cleanup acquire no new path; their existing owners remain authoritative. Concurrent valid and invalid requests use independent parser state, workdirs, captures, and outputs. No `.new`, `.install`, `.wwtxn.*`, cold scratch, test process, or capture residue survives the observed failure boundaries. The WW-native `imports_precede_other_top_level_declarations` observer proves direct compiler parity, exact recovery-section counts, selected and imported build rejection, syntax-before-resolution precedence, all directory test source variants, wrong-platform exclusion, valid runtime behavior, declared name versus canonical identity, cold/warm persistence and rollback, restored reuse, concurrent isolation, diagnostic equality, retained executable equality, and intermediate artifact-byte equality. The C parser unit and the existing `sepimport` observer separately pin the imports-only AST recovery and valid file-scoped binding regression. Rejected source creates no persisted byte contract, while valid source bytes are unchanged. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.42 Implemented per-source UTF-8 BOM placement Every eligible physical WW source may begin with one UTF-8-encoded U+FEFF byte order mark (`EF BB BF`). That marker is ignored, and the following token keeps its three-byte source position at line 1, column 4. U+FEFF at any later raw source position is rejected once as `invalid BOM in the middle of the file`, including inside a line/block comment, string, or rune. Two leading markers therefore ignore the first and reject the second. A truncated marker or another invalid UTF-8 byte sequence retains the ordinary byte-error path; UTF-16 source is not introduced. #### Pinned Go evidence and applicability The sole authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - compiler reader `(*source).nextch` decodes UTF-8, skips U+FEFF at its first source position, and reports `invalid BOM in the middle of the file` elsewhere ([`cmd/compile/internal/syntax/source.go`, lines 113–165](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/source.go#L113-L165)); - public scanner `(*Scanner).next` rejects later U+FEFF and `(*Scanner).Init` consumes the first one ([`go/scanner/scanner.go`, lines 58–100 and 128–164](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/scanner/scanner.go#L58-L164)); - scanner tests assert the ignored first marker and later markers between tokens, in comments, runes, and strings ([`go/scanner/scanner_test.go`, lines 371–374 and 812–815](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/scanner/scanner_test.go#L371-L374), [`go/scanner/scanner_test.go`, lines 812–815](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/scanner/scanner_test.go#L812-L815)); - compiler-scanner `TestScanErrors` asserts the positioned later-marker error ([`cmd/compile/internal/syntax/scanner_test.go`, lines 587–599](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/scanner_test.go#L587-L599)); and - official command testdata places the marker before `package main` and loads that source's imports and embedded file ([`cmd/go/testdata/script/build_ignore_leading_bom.txt`, lines 1–25](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_ignore_leading_bom.txt#L1-L25)). Those source branches and assertions are **behavior directly implemented or asserted by pinned Go**. Applying the first position independently to every WW physical source before its existing synthetic aggregate boundary is **behavior derived from the pinned implementation**. The pre-fix Cstage/WWstage failures on leading markers and successes for markers in comments/strings were **directly measured WW behavior**. The behavior honestly applies inside WW's local, dotted-import, manifest-free model: it is source representation before package and import interpretation. It requires no module, manifest, registry, lock, cache, database, CAS, network resolution, generalized import syntax, build expression, or normalized identity. #### Ownership and four-axis result `lexinit`, `lpeek`, `lget`, and `lexnext` in `cmd/wcc/lex.c`, with their twins in `lib/ww/syntax/lex.ww`, are the language owners. They skip the exact initial marker while advancing the logical column by its encoded width, recognize a later marker as one code point in every lexical context, and emit one stage-identical diagnostic. `sep_emit_body` in `cmd/ww/main.c` and `sepemitbody` in `selfhost/cmd/ww/main.ww` replace the optional marker with three spaces in every physical body placed after a synthetic `//ww:module-reset`, preserving columns; direct and imports-only lexer input remains independently correct. The shared package coordinator's `pkgclause` in `internal/wwpackage/package.ww` begins its pre-discovery package-name scan after the same optional marker. It does not replace the complete stage-driver scan. - **Go-like build:** a selected command, library, or imported dependency may use the marker in each eligible source. Multiple physical marked sources compose normally, command publication succeeds, and the executable runs normally. A later marker rejects during source loading before graph/action construction or compiler, assembler, archiver, linker, install, or runtime work. A source error keeps precedence over a missing import. - **Go-like test:** production, same-package, external-package, and test-only files each receive the offset-zero allowance. Valid variants build and run through the ordinary single directory product. A later marker yields the existing attributable `FAIL\n` result without a variant, generated main, test process, accounting, or retained binary. - **Go-like package:** package-clause recognition now begins at the pinned logical source start in direct compilers, directory drivers, and the shared coordinator. Declared names, source roles, package conflicts, command/test family selection, and canonical identity do not change. - **Go-like import:** imports following a legal marker and imports in a marked dependency retain their exact source spelling, file scope, qualifier, contextual local/vendor resolution, case-sensitive canonical dotted identity, visibility, cycle, and initialization behavior. The marker never becomes an edge or identity component. Fixed-target filename selection remains earlier than parsing: an excluded `_windows.ww` or `_windows_test.ww` contributes no marker diagnostic, package, import, graph, action, artifact, or invalidation state. For valid inputs, graph nodes, scheduling, producer arguments, initialization, runtime, result order, and publication are unchanged. Legal marker bytes become three position-preserving spaces only in the synthetic unit. Adding or removing the marker therefore changes unit content and invalidates source-derived actions, while semantic interface, assembly, object, archive, initializer, and executable content remains the same; every form remains Cstage/WWstage byte-identical. Cold rejection leaves no product, work generation, adjacent scratch, capture, `.new`, `.install`, or `.wwtxn.*`. A warm later-marker edit preserves the entire committed generation, tool vouchers, stamp, and public executable. Restoring the exact legal leading form recreates the same unit and reuses committed compiler/assembler/archive work before the normal link/publication boundary. Concurrent valid and invalid requests keep independent lexer/coordinator state, workdirs, captures, diagnostics, and products. Because later-marker rejection occurs before a producer or test child, producer/runtime failure, signals, timeouts, interruption, and process-group cleanup gain no new branch; their existing owners remain authoritative. The C lexer unit, WW syntax unit, and WW-native `utf8_bom_is_per_source_and_only_first` observer prove initial position, later-marker lexical contexts, direct frontend diagnostics and assembly, selected/imported multi-source build, wrong-target exclusion, every test source role, test-only execution, syntax-before-resolution precedence, cold cleanup, warm rollback and reuse, concurrent isolation, publication/runtime behavior, and complete stage diagnostic/artifact parity. No persisted format changes. Previously valid marker-free bytes are unchanged; previously leading-marked requests could not commit a generation; and diagnostic text is not a persisted-byte contract. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.43 Implemented selected-source U+0000 rejection Every selected physical `.ww` source rejects a raw byte `00` (U+0000) at its physical line and byte column with exactly `invalid NUL character`. The rule is source-wide: comments, interpreted-string text, rune text, and between-token positions cannot turn a raw NUL into payload. An escape spelling such as `\x00` remains a legal literal value because it is not byte `00` in the source file. This section is only the raw-U+0000 rule: malformed UTF-8 and the independently implemented per-source BOM boundary in §11.42 are not changed or broadened here. #### Pinned evidence, applicability, and measured prior behavior The sole authority is official Go 1.26.5 at `c19862e5f8415b4f24b189d065ed739517c548ba`. Its compiler owner, `(*source).nextch` in [`cmd/compile/internal/syntax/source.go`, lines 113–165](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/source.go#L113-L165), detects ASCII zero at lines 121–129, reports `invalid NUL character`, and continues decoding. `TestScanErrors` pins the positioned diagnostic at [`cmd/compile/internal/syntax/scanner_test.go`, lines 587–600](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/scanner_test.go#L587-L600), and compiler testdata [`test/nul1.go`, lines 7–52](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/nul1.go#L7-L52) requires NUL errors in strings, raw strings, line/block comments, and ordinary source. Go's independent public scanner has the same rule in [`go/scanner/scanner.go`, lines 63–108](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/scanner/scanner.go#L63-L108) and its tests at lines 790–819. These are **behavior directly implemented or asserted by pinned Go**. Before this change, directly measured Cstage and WWstage package builds both accepted a NUL in a line comment, wrote it into the committed synthetic unit, published byte-identical archive/interface products, and allowed a dotted local importer to link and run. The retained audit commands used `out/bin/ww` and `out/bin/ww_ww` with `WW_SRCLIB=/home/kimchi/src/ww/lib` over `/tmp/ww-pkgaudit.qtjcpO/src/nulcomment`; both exited zero with empty streams. The same acceptance applied to raw NUL in strings and runes. Those observations are **directly measured WW behavior**. Applying pinned Go's physical-source rule independently to WW's selected files is **behavior derived from the pinned implementation** and is applicable without importing Go's module, manifest, registry, lock, cache, database, CAS, network, generalized-import, or source-level build-expression model. #### Ownership, timing, and four axes The direct-frontend semantic owners are the logical source-decoder helpers in `cmd/wcc/lex.c` and their exact twins in `lib/ww/syntax/lex.ww`: each raw zero is consumed, reports the same positioned error, and is omitted before token recovery. Filtered token spans preserve that decoder rule through identifiers, numbers and suffixes, directives, escapes, operators, comments, and EOF. The line-comment decoder consumes each body once before classifying an internal module directive, so NUL filtering does not make generated path handling superlinear. The shared `internal/wwpackage/package.ww` coordinator owns public package/test diagnostic precedence: its length-aware preflight reports every raw NUL in an invalid physical source before its manual package-clause classifier. It is not another identity policy. Driver source slurping and synthetic-unit composition preserve byte lengths and are not semantic owners. - **Go-like build:** after fixed-target filename selection, an invalid selected root or dependency rejects during loading, before graph completion and before compiler, assembler, archiver, linker, install, publication, or execution. Source rejection in a root precedes resolution of that root's missing imports. A wrong-target file is excluded before this rule and remains unread by its semantic owners. - **Go-like test:** selected production, same-package, external-package, and test-only source each receive the rule before variant construction. Failure emits the established attributable `FAIL\n` without a generated main, test process, accounting, `ok` result, retained binary, or public test product. - **Go-like package:** each selected physical file owns its diagnostic and position. Declared package name, source role, package conflict handling, command/test family, physical directory, and exact canonical dotted identity are unchanged. - **Go-like import:** invalid bytes create no import edge or graph node. Valid import spelling, aliases, local/vendor/internal resolution, visibility, cycle handling, and initialization order remain unchanged. Thus raw NUL is never an input to manifest-free package identity, graph/action keys, symbols, `.wwi`, archive naming, publication names, or persistence keys. It neither changes local dotted-import boundaries nor introduces a manifest. #### Failure, publication, persistence, and parity Cold invalid requests create no unit, assembly, object, archive, executable, capture, `.new`, `.install`, `.wwtxn.*`, or public output. A warm edit that introduces NUL stops before a producer or install action, preserving the prior committed unit/interface/assembly/object/archive generation, tool vouchers, stamp, and public output byte for byte. Removing the NUL restores the ordinary selected-source fingerprint; exact restoration may reuse the earlier generation. Existing producer/runtime failure and transaction rollback remain their own owners because this branch creates no new rollback mechanism. Lexer and coordinator state are request/source-local. Concurrent valid and invalid requests keep independent workdirs, captures, diagnostics, and products; an invalid request cannot contaminate a valid sibling. The rule adds no process, wait, or cancellation boundary, so signal, timeout, interruption, process-group cleanup, and ordinary scratch cleanup retain their established owners. Validation itself leaves no durable residue. Cstage and WWstage are semantic twins: diagnostics match exactly, and valid unit/compiler/product bytes retain their existing byte-identity contract. `raw_nul_is_rejected_in_every_selected_source` in `test/package/package_test.ww`, with focused C and WW lexer coverage, proves literal and comment contexts plus adjacency recovery across escapes, identifiers, numbers and typed suffixes, operators, comment delimiters, and EOF; it also proves selected/imported builds, wrong-target exclusion, every directory-test source role, precedence, cold cleanup, warm rollback and reuse, concurrent isolation, valid escaped-NUL behavior, runtime/publication behavior, and no-residue/parity observations. No format bump. This changes invalid-source acceptance and diagnostics only; valid source composition and valid `.wwi`, assembly, object, archive, executable, and retained-test-product bytes are unchanged. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.44 Implemented exact output-option name and value semantics The `ww build` and `ww test` output option has the exact registered name `o`. Its accepted forms are `-o VALUE`, `--o VALUE`, `-o=VALUE`, and `--o=VALUE`. An equals form splits at the first `=` and preserves the complete remaining value, including an empty value and additional `=` bytes. Repeated occurrences are last-value-wins. A final empty value means no effective explicit output: a single command uses its ordinary default, a multi-command build performs its ordinary no-public-output build, a running test retains no copy, and compile-only testing uses its ordinary default retained name. Concatenated names such as `-oVALUE` and `--oVALUE` are unknown flags rather than output requests. Build option parsing stops at the first root operand; test parsing continues to recognize known test options, including exact `o`, on either side of its package operands. #### Pinned evidence and fact classification The sole authority is official Go 1.26.5 at `c19862e5f8415b4f24b189d065ed739517c548ba`: - `init` registers exactly string flag name `o` for the build command in [`cmd/go/internal/work/build.go`, lines 241–248](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L241-L248), and `invoke` parses that flag set before passing only remaining operands to `runBuild` in [`cmd/go/main.go`, lines 290–322](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/main.go#L290-L322). - `(*FlagSet).parseOne` accepts one or two leading dashes, splits the first `=`, consumes the next argument only when there was no equals delimiter, and rejects an unregistered concatenated name in [`flag/flag.go`, lines 1074–1146](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/flag/flag.go#L1074-L1146). `(*FlagSet).Parse` stops at the first non-flag operand at lines 1149–1176. `stringValue.Set` and `(*FlagSet).Set` overwrite a repeated string value at lines 240–250 and 494–528. `runBuild` derives effective explicit output from the final value's nonzero length and otherwise selects its default behavior in [`cmd/go/internal/work/build.go`, lines 459–478](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L478). - Build command testdata uses an equals-delimited output successfully in [`version_buildvcs_nested.txt`, line 57](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/version_buildvcs_nested.txt#L57). `testParse` exercises exact names with two leading dashes and separate values at [`flag_test.go`, lines 164–215](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/flag/flag_test.go#L164-L215), `TestUserDefined` asserts an equals-delimited string value at lines 251–267, and `TestUsage` asserts unknown-flag failure at lines 153–161. - Test command `init` registers exactly string flag name `o` in [`cmd/go/internal/test/testflag.go`, lines 32–38](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/testflag.go#L32-L38). `cmdflag.ParseOne` accepts one or two dashes, cuts the first `=`, preserves empty and remaining-equals value bytes, and rejects unknown names in [`cmd/go/internal/cmdflag/flag.go`, lines 53–118](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/cmdflag/flag.go#L53-L118). `testFlags` recognizes known flags before and after the package list and rejects an unknown flag with `-c` in [`cmd/go/internal/test/testflag.go`, lines 219–349](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/testflag.go#L219-L349). `testNeedBinary` and the output-classification branch treat final empty `testO` as no explicit retained destination in [`cmd/go/internal/test/test.go`, lines 631–646 and 771–781](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L631-L781). - Official command testdata uses compile-only test output successfully in [`devnull.txt`, lines 3–8](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/devnull.txt#L3-L8) and [`test_race_tag.txt`, lines 1–9](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_race_tag.txt#L1-L9). [`test2json_interrupt.txt`, line 10](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test2json_interrupt.txt#L10) places `-o` after a package operand, while [`test_flag.txt`, lines 11–16](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/test_flag.txt#L11-L16) asserts unknown-flag rejection with `-c` across supported placements. Those registrations, parser branches, effective-output branches, and official assertions are **behavior directly implemented or asserted by pinned Go**. Applying their exact-name, first-equals, final-value, and command-placement rules to WW's local command surface while retaining WW's diagnostic wording is **behavior derived from the pinned implementation**. The measured WW matrix below is **directly measured WW behavior**; no installed host Go result is used as authority. #### Direct pre-fix Cstage and WWstage matrix Both stages had identical pre-fix behavior in every row: | Route and spelling | Directly measured pre-fix result | | --- | --- | | single build, `-o=name` | exited 0 with empty streams, left `name` absent, and published executable `=name` | | single build, `-oname` | exited 0 with empty streams and incorrectly accepted the concatenated name | | single build, `--o name` or `--o=name` | exited 2 with empty stdout and byte-identical `ww build: unknown flag\n` stderr | | single build, final `-o=` | exited 0 with empty streams and published literal file `=` rather than the default command name | | build values containing `=` | retained an erroneous leading `=`; repeated separate forms were already last-value-wins | | build option after the first root | remained package input rather than being reparsed, matching the required placement boundary | | two-command coordinator, `-o=DIR/` | published both products beneath a literal leading-`=` directory | | two-command coordinator, `-oDIR/` | incorrectly accepted the joined name and published beneath the requested directory | | two-command coordinator, final `-o=` | exited 2 as `cannot use -o with multiple packages` instead of selecting no effective explicit output | | compile-only directory test, `-o=name` | exited 0 with empty streams, left `name` absent, and published test binary `=name` | | compile-only directory test, `-oname` | incorrectly accepted the concatenated name and published that retained binary | | compile-only directory test, `--o=name` | exited 2 with empty stdout and byte-identical `ww test: unknown flag\n` stderr | | compile-only directory test, final `-o=` or a value containing `=` | published literal `=` or an erroneous leading-`=` destination | | test `-o` after its package operand | was already recognized, matching the required test placement boundary | The wrong-path single-build executables were stage-byte-identical 4,268-byte files with SHA-256 `866c1eb875dad271d37572f43fb9d9b0eb6a2344d2e61646e655bb09f7909bf6`. The wrong-path retained test binaries were stage-byte-identical 112,829-byte files with SHA-256 `5ea3ac9add844dc4cd98cc07fb64816415b5e3c03745dc4cc756ec093cf5cea7`. The build and test unknown-flag diagnostics were respectively 23 and 22 bytes, also byte-identical between Cstage and WWstage. These byte counts and hashes describe only the direct pre-fix measurements. #### Ownership and complete four-axis result The Cstage command owners are `parse_build_flags` and `do_test` in `cmd/ww/main.c`. Their WWstage semantic twins are `dobuild` and `dotest` in `selfhost/cmd/ww/main.ww`. The shared multi-package owner is `packagecommand` in `internal/wwpackage/package.ww`. Each recognizes exact one-/two-dash separate/equals forms, replaces prior occurrences with the final value, and derives effective explicit-output state from that final value's non-emptiness. The build parser retains its first-root stop, while test and the coordinator retain their established after-package recognition. `dorun` and the shared `run` route are not changed. The compiler, assembler, archiver, linker, runtime, package checker, and import resolver do not own this rule. - **Go-like build:** exact accepted forms select the same established output path as separate `-o VALUE`; a final empty value selects the existing default/no-public-output branch. Invalid concatenated names reject before loading, graph or action construction, producers, publication, or runtime. - **Go-like test:** the same exact forms select retained destinations on both sides of package operands. Final empty means no running-test retention or the normal compile-only default. Discovery, variants, generated main, filtering, execution, accounting, result annotation, and absence of a test-result cache do not change. - **Go-like package:** output bytes remain presentation metadata. Source eligibility, package clauses, declared names, variants, command classification, canonical package representatives, graph nodes, actions, symbols, artifacts, and persistence keys are unchanged. - **Go-like import:** output spelling creates no binding or edge and changes no dotted import spelling, alias, search, local/vendor/internal rule, visibility, cycle, initialization order, canonical identity, or `.wwi` ownership. #### Loading, lifecycle, parity, and proof Accepted forms enter the same existing loading, graph, scheduling, compiler, assembler, archiver, linker, runtime, publication, persistence, reuse, and invalidation paths as `-o VALUE`. They add no action, process, transaction, cache, key, artifact byte, or runtime state. Producer or runtime failure, late output rejection, rollback, prior-state preservation, concurrent publication, interruption, and process-group cleanup therefore retain their established owners and results. Output installation keeps the existing transaction, object-safety, mode, null-device, output-directory, and running-retained-test guard rules. Invalid concatenated names stop before all loading and work, create no diagnostic competitor or product, and leave no unit, interface, assembly, object, archive, executable, retained test binary, capture, output prefix, `.new`, `.install`, `.wwtxn.*`, or scratch residue. A final empty value cannot create literal `=`, `=.sepwork`, or transaction residue. Cold and warm accepted requests use the ordinary publication and reuse paths; changing only an accepted spelling does not rekey semantic work. Independent concurrent requests own independent argument state, workdirs, stages, captures, and outputs. Build starts no runtime; running tests keep their private executable and publish only after successful execution. The WW-native `output_flag_exact_name_and_value_semantics` observer is the focused owner for both public stages and all three parser routes. It covers the four accepted forms, extra and empty equals values, repetition, concatenated name rejection, build/test placement controls, multi-command behavior, diagnostic parity, runnable and retained artifact-byte parity, warm reuse, and absence of literal-equals and transaction residue. Existing transaction, producer/runtime failure, rollback, concurrency, interruption, output-mode, and cleanup observers remain authoritative for the unchanged downstream mechanisms. Post-fix byte counts and hashes are recorded only after direct focused measurement; this section does not infer them from the implementation. This is command parsing and output presentation only. No persisted-byte contract changes: build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. ### 11.45 Implemented selected-source malformed UTF-8 rejection Every malformed UTF-8 byte in an eligible selected physical `.ww` source is rejected at its 1-based physical line and raw-byte column with exactly `invalid UTF-8 encoding`. The source decoder consumes that byte, omits it from the logical character stream, and resumes. Consequently, a malformed multi-byte spelling is diagnosed once for every byte that decodes as U+FFFD with width one, while a correctly encoded U+FFFD remains valid. Validation is source-wide: comment and literal contexts do not hide malformed bytes, and an invalid byte cannot split an identifier, number or suffix, operator, escape, comment delimiter, package keyword, or import spelling into a different token. This section adds only malformed-UTF-8 validation. It does not reopen the per-source leading-BOM contract in §11.42, raw-U+0000 rejection in §11.43, or exact output-option parsing in §11.44. BOM, raw NUL, and malformed UTF-8 remain independent positioned source conditions and are handled in raw-byte order. #### Pinned evidence, applicability, and fact classification The sole authority is official Go 1.26.5 at `c19862e5f8415b4f24b189d065ed739517c548ba`: - compiler reader `(*source).init`, `(*source).pos`/`error`, and `(*source).nextch` establish the 1-based byte-positioned decoding boundary in [`cmd/compile/internal/syntax/source.go`, lines 60–88 and 113–165](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/source.go#L60-L165); - `(*source).nextch` calls `utf8.DecodeRune` at lines 149–150, and a U+FFFD result of width one reports exactly `invalid UTF-8 encoding`, consumes that one byte, and resumes at lines 152–154; - compiler-scanner `TestScanErrors` asserts the positioned malformed byte and truncated-`EF` regression in [`cmd/compile/internal/syntax/scanner_test.go`, lines 587–600 and 658](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/scanner_test.go#L587-L658); - compiler testdata requires UTF-8 errors in interpreted and raw strings, comments, identifiers, and ordinary source in [`test/nul1.go`, lines 7–52](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/nul1.go#L7-L52); - the independent public scanner corroborates width-one malformed decoding in [`go/scanner/scanner.go`, lines 63–108](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/scanner/scanner.go#L63-L108) and its literal test at [`go/scanner/scanner_test.go`, lines 810–811](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/scanner/scanner_test.go#L810-L811); - directory enumeration, filename eligibility, source reading, and test-role classification are ordered by `Context.Import`, `Context.matchFile`, and `Context.goodOSArchFile` in [`go/build/build.go`, lines 859–953 and 1005–1036](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L859-L1036), [`Context.matchFile`, lines 1438–1509](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1438-L1509), and [`Context.goodOSArchFile`, lines 1980–2027](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1980-L2027), while internal/external test variants consume those selected lists in [`cmd/go/internal/load/test.go`, `TestPackagesAndErrors`, lines 85–102 and 175–240](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L85-L240). Those decoder branches, source-selection branches, and official assertions are **behavior directly implemented or asserted by pinned Go**. Applying the same per-selected-physical-source rule to `.ww` inputs, after WW's fixed-target filename/test-role eligibility and before its package/import interpretation, is **behavior derived from the pinned implementation**. It honestly applies to WW's declared UTF-8 source without adding modules, manifests, registries, lock files, caches, databases, CAS, network resolution, quoted/grouped/dot/general imports, or a source-level build language. Before this change, the following observations were **directly measured WW behavior**: - direct `w6c` and `w6c_ww` accepted comments containing stray continuation `80`, lead `FF`, overlong `C0 80`, and surrogate `ED A0 80` bytes, exited zero with empty streams, and emitted byte-identical 89-byte assembly with SHA-256 `7385e3ce0107324edc94ee4377c5c2b0262c5b690939cb54f599ed09f9730db8`; - both direct compilers accepted raw `FF` in a string and emitted byte-identical 236-byte assembly with SHA-256 `4dbe79617badb56d541526ca276a9867d0d717ad9aa0c540f629882f87e3f3ad`, while valid Korean and accented controls remained accepted and stage-identical; - both public build stages accepted malformed comments and literals, published runnable binaries, and built and ran an imported dependency containing malformed UTF-8; that dependency executable was 4,317 stage-identical bytes with SHA-256 `f792da043743cc512c9d9a41deb4cb4af1e42d35e2716fcd5b57355fd7f566eb`; - malformed production, same-package, external-package, and test-only selected sources ran successfully in both stages; one same-package compile-only binary was 112,829 stage-identical bytes with SHA-256 `108150d071a3ab4264d021d2c3fdc7a94ff71a00153fdf14bfe8e26520cc5da2`; - a corrupted `package` produced a package-clause diagnostic plus `unexpected character 0xff` in Cstage but a generic `unexpected character` in WWstage, with 176-byte versus 171-byte stderr; corrupted imports reached analogous fallback recovery rather than the pinned decoder diagnostic; - malformed source before `import nowhere;` allowed missing-import resolution to win, while a malformed same-package test keyword reached the coordinator's unpositioned `invalid or missing package clause`; and - malformed wrong-target and ordinary-build-excluded test files were ignored, and reverse-created selected files were still diagnosed in byte-sorted name order. No installed host Go result supplies any authority or measurement above. #### True ownership and complete four-axis result The semantic owners are the source-decoder twins in `cmd/wcc/lex.c` and `lib/ww/syntax/lex.ww`, plus the selected-physical-source preflight in `internal/wwpackage/package.ww`. The decoders enforce bytewise recovery for complete direct and composed compiler inputs. The shared coordinator enforces the same validation before its textual package-clause classifier and import discovery, so a coordinator fallback cannot outrank the physical-source error. The Cstage/WWstage package-unit composers only transport already admitted source bytes and are not additional owners. - **Go-like build:** each eligible selected root, library, or dependency source is validated before its imports complete the graph or any compiler, assembler, archiver, linker, install, publication, or runtime action starts. A source error in a selected root precedes missing, self, cycle, `internal`, vendor, and imported-command resolution. Wrong-target and test-only files excluded from ordinary build are not semantic inputs and are not decoded. - **Go-like test:** production, same-package, external-package, and test-only selected physical sources are validated before grouping or variant/product construction. Rejection builds no support action or generated main, starts no test process, emits no accounting or package `ok` line, and retains or publishes no executable. An attributable explicit request keeps its existing command-owned final `FAIL\n` presentation. - **Go-like package:** each selected physical file owns its positioned errors; selected filenames retain byte-sorted order. Correctly encoded non-ASCII content remains legal in WW's permitted comment/literal contexts. Declared package names, source roles, package conflicts, command/test classification, and variant boundaries do not change. - **Go-like import:** a malformed byte is filtered before it can manufacture, split, or change an import occurrence, qualifier, or edge. Valid spelling, aliases, file-scoped binding, local/vendor/internal resolution, visibility, cycle detection, graph order, and initialization remain unchanged. Canonical dotted package and import identity remains exact and case-sensitive. Physical directory, declared name, alias, path leaf, filename, source bytes, artifact name, output path, and linker order remain loader, runtime, or presentation metadata only where already specified; none becomes package, graph, action, symbol, `.wwi`, publication, or persistence identity. #### Loading, graph, action, runtime, and diagnostics Filename and test-role eligibility occurs first. The shared preflight then scans eligible selected files in existing byte-sorted order, reporting every malformed byte in the first invalid physical file in position order before package-clause classification. Lines and columns advance by raw source bytes. A legal leading BOM still advances three columns, raw NUL keeps its own exact diagnostic, and the three source conditions interleave without one being reclassified as another. An invalid source completes no package node, import edge, test variant, support action, or generated-main action. No compiler, assembler, archiver, linker, installer, or runtime process is scheduled for that invalid request. Independent valid siblings and requests keep the established command-global planning and scheduling rules; validation adds no global state and cannot cancel or mutate them. Valid loading, graph identity, action order, initialization, runtime behavior, result order, and output selection are explicit non-effects. Diagnostics use exact text `invalid UTF-8 encoding` with path, 1-based line, and 1-based raw-byte column. Each width-one malformed decode is consumed and removed before token recovery, preventing a second stage-specific package, import, identifier, literal, operator, escape, or EOF interpretation. Complete direct frontend inputs report all malformed bytes. Public package/test loading uses the same sequential physical-source preflight and therefore preserves Cstage/WWstage diagnostic-byte parity and source-before-resolution precedence. Existing valid-input, BOM, NUL, package, import, and output-option diagnostics retain their owners and wording. #### Publication, persistence, artifacts, and failure lifecycle Cold malformed-source rejection creates no synthetic unit, `.wwi`, assembly, object, archive, executable, retained test binary, result status, capture, or published output. It leaves no `.new`, `.install`, `.wwtxn.*`, adjacent `.sepwork`, tool-stage transaction, or scratch residue. Invalid input has no artifact-byte comparison beyond identical absence. Warm rejection commits no generation and preserves every prior unit, interface, assembly, object, archive, tool record, stamp, executable, retained binary, and public output byte for byte. Because staging has not begun, the source branch requires no new rollback mechanism. Restoring the exact valid source follows ordinary content comparison and may reuse the prior committed generation. Valid Cstage and WWstage unit, interface, assembly, object, archive, generated-main, executable, and retained-test bytes keep their existing byte-identity contract. Producer failure, runtime failure, publication-only failure, and cleanup-only failure remain downstream owners and are not redefined; malformed-source rejection makes those phases unreachable for the invalid request. Validation state is source/request-local. Concurrent valid and invalid requests retain independent workdirs, outputs, captures, diagnostics, processes, and transactions. The change adds no process, wait, signal, timeout, cancellation, or interruption boundary, so existing process-group ownership, interruption, rollback, and cleanup remain unchanged. The recipe-owned fixed `out/bootstrap` tree is not transaction residue. #### Proof, twin parity, and formats Focused C and WW lexer proofs cover valid encodings and encoded U+FFFD; invalid leads and continuations; overlong, surrogate, out-of-range, truncated, and repeated malformed spellings; token boundaries; and BOM/NUL interaction. The WW-native `malformed_utf8_is_rejected_in_every_selected_source` observer owns direct compiler, root/dependency build, source/import precedence, every test source role, wrong-target selection, cold/warm rejection, exact restoration and reuse, valid sibling concurrency, artifact absence, residue cleanup, stage diagnostic parity, and valid-artifact byte parity. Concrete post-change byte counts, hashes, and gate results are recorded only after focused and full validation; they are not inferred from the implementation. No format bump. This changes invalid-source acceptance and diagnostics only; the valid persisted-byte contract is unchanged. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. No test-result cache is introduced. ### 11.46 Implemented effective-`init` import-binding recovery An import whose effective file-local qualifier is `init` is rejected as `cannot import package as init - init must be a func`. The rule covers an explicit `init` alias and an unaliased dependency declared `package init`. Every resolved rejected occurrence reports the core error at the first import-spec token: the alias token when explicit, otherwise the first path token. The occurrence creates no qualifier and takes no part in unused, duplicate-binding, or declaration/import-collision recovery. A later `init.Name` therefore recovers independently as undefined. Resolution retains precedence, so a missing target fails without an additional effective-`init` diagnostic. Only the file-local binding is rejected. The resolved source occurrence and its exact dotted dependency remain loader and graph provenance. Neither the effective qualifier nor the dependency's declared package name becomes canonical package, import, graph, action, symbol, `.wwi`, artifact, publication, or persistence identity. The paragraphs above state the normative implementation contract and are **behavior derived from the pinned implementation**. The post-change results recorded in the proof subsection below are **directly measured WW behavior**. #### Pinned evidence and fact classification The sole authority is official Go 1.26.5 at `c19862e5f8415b4f24b189d065ed739517c548ba`: - `(*Checker).collectObjects` resolves an import at lines 248–263, selects the explicit alias or imported declared name at lines 264–274, rejects effective name `init` and immediately continues at lines 275–278, before explicit import recording, `PkgName` construction, used-import tracking, or file-scope installation at lines 280–335 in [`cmd/compile/internal/types2/resolver.go`, lines 223–335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L223-L335); - `(*Checker).unusedImports` examines only admitted imports at [`cmd/compile/internal/types2/resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740), while package/file collision reconciliation is at lines 472–489 of that file; - the independent public checker implements the same effective-name rejection and immediate continuation in [`go/types/resolver.go`, lines 261–315, especially 290–293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L261-L315); - compiler-syntax `(*parser).importDecl` assigns the declaration position to the first import-spec token in [`cmd/compile/internal/syntax/parser.go`, lines 543–574](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/parser.go#L543-L574), with node-position ownership in [`cmd/compile/internal/syntax/nodes.go`, lines 10–31 and 56–64](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/nodes.go#L10-L64); - public `ast.ImportSpec.Pos` independently chooses the alias position when present and the path position otherwise in [`go/ast/ast.go`, lines 908–915 and 939–946](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/ast/ast.go#L908-L946); - compiler diagnostics are stably position-sorted in [`cmd/compile/internal/base/print.go`, lines 70–92](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/base/print.go#L70-L92); and - package loading and action construction remain separate from file binding in [`cmd/go/internal/load/pkg.go`, lines 757–805](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L757-L805) and [`cmd/go/internal/load/pkg.go`, lines 2024–2047](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2024-L2047), [`cmd/go/internal/work/action.go`, lines 647–658](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/action.go#L647-L658), and test-variant construction in [`cmd/go/internal/load/test.go`, lines 175–240](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L175-L240). Official assertions are [`internal/types/testdata/check/importdecl0/importdecl0a.go`, lines 9–17](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/importdecl0/importdecl0a.go#L9-L17), which expects only the core error for an explicit `init` alias; [`test/fixedbugs/issue4517d.go`, lines 7–9](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/fixedbugs/issue4517d.go#L7-L9), which covers the explicit spelling; and [`test/fixedbugs/issue43962.dir/a.go`, lines 1–5](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/fixedbugs/issue43962.dir/a.go#L1-L5) with [`b.go`, lines 1–7](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/fixedbugs/issue43962.dir/b.go#L1-L7), which covers an imported package declared `init`. Those resolver, syntax-position, loader/action branches and official assertions are **behavior directly implemented or asserted by pinned Go**. The immediate continuation proves that the rejected occurrence contributes no unused, duplicate-binding, or declaration/import-collision recovery; every rejected occurrence reports independently; a later selector sees no package binding; and missing resolution wins before effective-name checking. The separate loader/action path proves that rejecting the qualifier does not erase the resolved dependency occurrence or change canonical identity. Those conclusions are **behavior derived from the pinned implementation**. They honestly apply to WW's local, unquoted dotted-import, manifest-free model without adding modules, manifests, registries, lock files, caches, databases, CAS, network resolution, quoted/grouped/dot/general imports, or a source-level build language. #### Fresh four-axis audit and direct pre-fix measurements The fresh audit also reconfirmed two applicable but unselected differences: multiple named source files remain different across build, test, package, and import construction; shared test-process state and ordinary-abort behavior remain different across test runtime and package/imported mutable state. They remain genuine future candidates and were not reclassified as aligned or inapplicable. Effective-`init` recovery was selected because the pinned resolver supplies one exact, bounded semantic owner whose complete binding and lifecycle effects can be closed without redefining either broader gap. Before this slice, the following observations were **directly measured WW behavior**. Every Cstage/WWstage pair had identical status, stdout bytes, stderr bytes, and artifact state: | Input | Status and stdout | Pre-fix stderr SHA-256 | Pre-fix recovery | |---|---|---|---| | explicit unused `init` alias | 1; empty | `5248382591e88562ba9c3c648af47523f617be0dcaf16586dc46a2517f76fe58` | bogus unused, then core | | explicit alias used by `init.value()` | 1; empty | `a3189e9aeaf56d5cb8aa63aa1a4de07d5176af531555a5834315298e4e9105a8` | core, then undefined | | implicit declared-name `init`, unused | 1; empty | `c77b3cf3b052727d90662c9b33ba85c10cba133d25b1d8b41dd53e32e1ab4978` | bogus unused, then core | | implicit qualifier used by `init.value()` | 1; empty | `cf0cf83a83077736497cd54a801762912f97ced4684d6c878257edbc79958340` | core, then undefined | | two rejected occurrences plus use | 1; empty | `9124e49408a710e1ed49a0b39b46b0967b9fe4c5f8bc67b21205d174bcfaebee` | bogus redeclaration/alternate and unused; two cores; undefined | | rejected import plus top-level `let init` | 1; empty | `b5e48cfab10e95d581d64d59e28409c63c7f450fa09c8d2bd11d2bb1bf487c08` | bogus unused/collision/alternate plus correct declaration/core errors | | missing target under alias `init` | 1; empty | `5c0fd415bb8bc8791bb87cf7211f69eea06b87ea63f264f5b8b526cbd8ac1fd9` | only missing-package error; aligned precedence | | same-package test, unused alias | 1; exact `FAIL\n` | `9b40aac1b160743787b4782a967350b9c97a4bf414ea0c05ea9b926c85403f9e` | bogus unused, then core | | external test, later use | 1; exact `FAIL\n` | `e3fcb66e8fe4eabaf2bbac0b510c370dd904fca90daab334ad4cd9b82ac914f3` | core, then undefined | Representative pre-fix output placed both the bogus unused diagnostic and the core error at generated-unit column 1, the `import` keyword: ```text ...unit.new:3:1: error: "pkg.normal" imported as init and not used ...unit.new:3:1: error: cannot import package as init - init must be a func ``` Repeated imports additionally reported `init redeclared in this block`; a top-level declaration additionally reported `init already declared through import of package init`. These were checker recovery artifacts forbidden by the pinned immediate continuation. Pinned position ownership maps WW's `import init ...` spelling to the alias at source column 8. Aligned controls succeeded in both stages with empty streams: blank `import _ pkg.normal;` emitted a stage-byte-identical artifact with SHA-256 `20847ada6923ab0bfd1dff6a3c387e0c5adace74152b84e895bc420a2e4134e9`, and used `import stable pkg.normal;` emitted a stage-byte-identical artifact with SHA-256 `1a8fefbc12d5ea4a2bca938db6fbcdb66f3a14bbc0f7371756e4b5862ed8935c`. Each rejected cold case created no new public artifact. A compiler wrapper recorded exactly two calls per stage—dependency compilation followed by root compilation with its canonical `.wwi`—and failure left the traced workdirs empty with no `.new`, `.install`, or `.wwtxn.*` residue. Changing the warm valid qualifier to `init` preserved the complete committed work-file manifest and public product byte for byte in both stages, with no active transaction residue. The direct pre-fix four-axis result was: - **Go-like build:** different diagnostic recovery and position; loading, graph, producer order, failure, cold no-publication, warm rollback, and cleanup were aligned; - **Go-like test:** different for same-package and external-test sources for the same checker reason; variant selection and final `FAIL\n` accounting were aligned; - **Go-like package:** different because a rejected qualifier spuriously participated in package-declaration collision recovery; canonical package identity was aligned; and - **Go-like import:** the core rejection and missing-import precedence were aligned, while binding admission, recovery exclusions, and diagnostic position were different. #### Ownership and complete four-axis contract The semantic owners are the transient import-spec position plus checker-local file-binding recovery: - Cstage: `N_USE` in `cmd/wcc/ww.h:319-375`, import parsing in `cmd/wcc/parse.c:1321-1359`, and binding/recovery in `cmd/wcc/check.c:2911-2972,3987-4144`; - WWstage: the `N_USE` twin in `lib/ww/syntax/ast.ww:108-158`, import parsing in `lib/ww/syntax/decl.ww:9-50`, and binding/recovery in `selfhost/cmd/wcc/check.ww:178-221,418-434,7531-7675,8601-8650`. Both parsers retain the existing import-keyword node position for unrelated structural diagnostics and record a transient first-spec-token position. Both checkers identify a nonblank resolved occurrence whose effective qualifier is exactly `init`, emit the core diagnostic in source order before qualifier-use, duplicate, unused, collision, or installation recovery, exclude it from every such table, and silently omit the rejected qualifier from file scope. The AST occurrence itself remains intact. Declared-name binding in `cmd/w6c/main.c:315-357` and `selfhost/cmd/w6c/main.ww:410-458`, driver graph construction in `cmd/ww/main.c:3396-3425,3630-3689` and its self-hosted twin, and all canonical dotted identity rules remain unchanged. - **Go-like build:** a resolved invalid root or dependency reaches the normal dependency action, then the owning compiler action rejects once per occurrence at the spec token without qualifier-recovery noise. Producer failure still prevents new publication and preserves a prior committed generation. - **Go-like test:** the same checker rule applies after existing filename and role selection to production-test, same-package-test, external-test, and test-only sources. Failed products keep command-owned `FAIL\n` accounting and are not installed; test runtime and process topology do not change. - **Go-like package:** rejected qualifiers do not collide with package-scope declarations. An imported declared name `init` remains the effective name tested for an implicit import, but declared name, source role, package identity, and package declaration semantics do not change. - **Go-like import:** explicit and implicit effective-`init` bindings reject at the alias/path spec token; every occurrence rejects; later `init.Name` is undefined; missing resolution keeps precedence; and rejected bindings create no unused, duplicate, or declaration-collision recovery. #### Loading, lifecycle, parity, and formats Filename/platform/test-role eligibility and selected-source UTF-8, BOM, NUL, package-clause, and import-order validation remain earlier and unchanged. Excluded and wrong-target files remain non-inputs. Existing dependencies load normally; a missing dependency fails before checker binding recovery. Exact canonical paths continue to own package nodes, sorted/deduplicated graph edges, action keys, symbols, `.wwi` files, artifacts, publication, and invalidation. Dependency compilation still precedes the rejecting root action; no action ordering, scheduling, transaction, concurrency, or package-product topology changes. Only transient parser/checker state changes. No valid compiler output, assembler, archiver, linker, initialization, runtime, test-runtime, or publication path changes. Invalid root input cannot complete its assembly, object, archive, link, retained-test, install, or runtime phases. Dependency or root producer failures, runtime failures, publication-only failures, and cleanup failures keep their existing owners and classifications. Cold rejection creates no new public or retained root product and commits no partial unit, `.wwi`, object, archive, executable, tool record, stamp, or result. Warm rejection preserves the previous complete committed generation and public product. Dependency reuse and ordinary source invalidation remain unchanged, and a rejected generation never replaces root state. The rule adds no process, signal, wait, timeout, cancellation, shared state, or lock, so established request isolation, interruption rollback, descendant cleanup, and concurrent valid/invalid request behavior remain unaffected. Failure leaves no active `.new`, `.install`, `.wwtxn.*`, adjacent `.sepwork`, capture, scratch, or tool-stage transaction residue; the fixed recipe-owned `out/bootstrap` tree is not transaction residue. The WW-native `effective_init_imports_never_enter_binding_recovery` observer owns explicit and implicit bindings; unused, used, repeated, declaration-collision, selector, and missing-target recovery; valid blank and explicit-alias controls; ordinary and imported builds; applicable production/same/external/test-only source roles; fixed-path stage status/stdout/stderr parity; invalid binding rejection inside a dependency reached through an imported root; cold empty-workdir rollback; warm preservation; valid artifact-byte parity; and residue cleanup. Concrete post-change statuses, diagnostic bytes and hashes, artifact hashes, and ordered full-gate results are recorded only after focused and full validation; they are not inferred from the implementation. No persisted-byte contract changes. Import-spec coordinates and recovery tables are transient compiler state. Build workdir format remains `18`, test workdir format remains `19`, semantic storage format remains `3`, and no test result cache is introduced. #### Direct post-fix proof and ordered validation The following results are **directly measured WW behavior**. Both rebuilt stages reject explicit and implicit effective-`init` bindings at spec-token column 8. Every occurrence produces one core error; rejected bindings produce no unused, duplicate-binding, declaration/import-collision, or alternate- location recovery. Independent invalid declarations and later undefined selectors remain diagnosed, while missing-package resolution retains precedence. A fixed-path explicit-unused probe produced identical Cstage and WWstage results: status 1, empty stdout, and 131-byte stderr with SHA-256 `615a06b827a41ce214b9e76049b402be94680a14ba5e3416455d7a628185c7d5`. The valid blank-plus-explicit-alias control ran with status 41 and had identical unit, `.wwi`, assembly, object, archive, generated-init, and executable bytes across stages. Its 4,317-byte executable had SHA-256 `64a48e8b18f035b8598fbe39feedc5a0e6df45d256305cb0f32e8b27a0471b92`. The WW-native observer passed for ordinary roots, a rejecting imported dependency, production-test, same-package-test, external-test, and test-only sources. It directly proved normalized diagnostic parity, cold empty-workdir rollback and no publication, warm preservation and exact reuse of every committed semantic file and public product, valid artifact-byte parity, and no active transaction residue. `out/bin/test_300_check` passed 73/73 checks. All ordered full gates then passed serially in the required order: 1. `make -j4 JOBS=4 test` 2. `make -j4 JOBS=4 test-commit` 3. `make -j4 JOBS=4 test-byteid` 4. `make -j1 JOBS=1 test-bootstrap` 5. `make -j1 JOBS=1 test-platform` 6. `make -j1 JOBS=1 test-all` The first byte-identity invocation encountered one transient `roster` timeout under four-way load. The exact isolated row passed, and the unchanged third gate was rerun successfully: 161 language files and 1,421 data fixtures were byte-identical with zero pinned divergences. Bootstrap reached the ww2/ww3/ww4 fixed point and round-tripped all five WWstage tools byte-identically; the platform gate produced a byte-identical dynamic-link result. No production code changed after the successful ordered sequence began. ### 11.47 Implemented empty-reason test skip classification Pinned Go's applicable semantic rule is that a test may skip without supplying a message, remains a successful skipped test, and does not prevent the next selected test from running. Mapping that rule to WW's already representable `test.skip("")` call is **behavior derived from the pinned implementation**. WW realizes that rule by writing a structurally valid `TST_SKIPPED` control frame with a zero-length payload and accepting it when the child otherwise exits normally with status zero. Presentation remains `qualified.name ... SKIP: ` followed immediately by newline. Skipped accounting increases once; failure and harness-error accounting do not. Nonempty reasons keep their existing behavior. A 4,094-byte reason remains an invalid control result, and skip outside an active test still aborts. Those WW-specific frame, presentation, bound, accounting, and outside-active details are **directly measured WW behavior** in the post-change proof below; they are not attributed to Go's implementation. #### Pinned evidence and fact classification The sole semantic authority is official Go 1.26.5 at `c19862e5f8415b4f24b189d065ed739517c548ba`: - [`(*T).Skip` and `(*T).SkipNow` in `testing/testing.go`, lines 1231–1259](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L1231-L1259) show `Skip` accepting a variadic argument list and logging `fmt.Sprintln(args...)` before calling zero-argument `SkipNow`; `SkipNow` marks and stops that test and explicitly permits the next test to continue; - [the package documentation in `testing/testing.go`, lines 273–293](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/testing.go#L273-L293) includes a zero-argument `t.Skip()`; and - official assertions in [`testing/sub_test.go`, lines 182–190](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/sub_test.go#L182-L190), [237–240](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/sub_test.go#L237-L240), and [341–346](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/testing/sub_test.go#L341-L346) mark message-less `SkipNow` and zero-argument `t.Skip()` cases successful. Those methods, documentation, and official assertions are **behavior directly implemented or asserted by pinned Go**: a message-less call is admitted and successful, is classified skipped, and permits the next selected test to run. That a suite containing this skip and otherwise passing selected tests has an overall successful result is **behavior derived from the pinned implementation**. The rule honestly applies within WW's local, dotted-import, manifest-free model: WW's public `test.skip` already takes a `str`, and that type already represents the applicable empty-reason case without adding Go syntax, modules, manifests, package-path conventions, regex filters, or a new build language. #### Fresh four-axis audit and direct pre-fix measurements The fresh audit classified multiple named source files, explicit `*_test.ww` build operands, shared top-level test-process state and abort boundaries, bare effective import bindings, and lexical import shadowing as applicable differences that remain unselected. Leading-underscore explicit source behavior retains a bounded applicability question, mixed declarations are aligned, and grouped, quoted, dot, and generalized imports are inapplicable to WW's import model. The exact explicitly named `*_test.go` build case lacks an official pinned testdata assertion even though pinned source derives its behavior, so it was not evidence-complete for this session. The empty-reason skip was selected because its complete observable meaning has one bounded shared-runtime owner and does not partially implement or redefine those broader differences. Before this slice, the following observations were **directly measured WW behavior**. The fixed-path probe `/tmp/ww-empty-skip-pre.Wkh1CW/pkg` defined production `marker()`, then test `first`, which called `test.skip("")`, and passing test `second`. Both Cstage and WWstage exited 1, wrote empty stderr, and emitted byte-identical 255-byte stdout with SHA-256 `ed5015be2946b902cd42819d36ad102af34c229732b477441dc4b285ed612be3`: ```text emptyskip.first ... HARNESS (malformed or contradictory result) emptyskip.second ... ok 1 passed, 0 failed, 0 skipped, 1 harness errors 2 discovered, 2 selected, 2 started, 2 completed FAIL /tmp/ww-empty-skip-pre.Wkh1CW/pkg [emptyskip] (test exit 1) FAIL ``` Filtering to `first` failed with one harness error in both stages; filtering to `second` succeeded; list mode succeeded and printed both names without executing either body. `test -c -o` succeeded with empty streams and produced stage-byte-identical 112,861-byte executables with SHA-256 `2d8f3a1adbd2f158ac605b4cecf9966a2b700ff0cc7f31aaa431bad3bc89e844`. Direct execution of those binaries failed identically, with stdout SHA-256 `b83ef1368512dd3d2ee46c5e6d1c08369b40eb4b849eae70303aebaef80ee650` and empty stderr. These are pre-fix measurements only. For that fixed fixture, the directly measured pre-fix four-axis result was: - **Go-like build:** both stages selected and built the production/test inputs sufficiently to publish byte-identical retained test executables; this probe did not independently trace graph/action topology; - **Go-like test:** empty-reason classification, result presentation, accounting, package status, and direct retained execution were different, while filtering, list non-execution, and later-test execution were aligned; - **Go-like package:** the production source and same-package test source formed one runnable package result; this probe made no external/test-only-role claim; and - **Go-like import:** `import test` resolved and linked in both stages; this probe made no separate qualifier, unused-import, or graph-provenance claim. The broader unchanged role, identity, graph, persistence, and lifecycle items below are implementation boundaries, not additional facts attributed to this pre-fix fixture. #### Ownership and complete four-axis contract The true semantic owner is the shared in-binary test control-frame producer and interpreter in `lib/test/run.ww`. Both stages link that one WW runtime; there is no duplicate C/WW implementation. The producer rejects only a reason larger than the control-frame payload limit and writes the empty `TST_SKIPPED` payload normally. After the existing header and exact-length checks, the interpreter accepts skipped code with payload length zero as well as positive length, while retaining the requirement for normal status-zero child termination. - **Go-like build:** ordinary source loading, graph/action construction and scheduling, compiler, assembler, archiver, linker, naming, and output publication semantics do not change. The source-content change invalidates and relinks affected products through existing dependency rules. Ordinary products that do not import `test` stay outside the changed source; an ordinary product that explicitly imports `test` may rebuild with changed artifact bytes, while its outside-active runtime abort remains unchanged. - **Go-like test:** every shared-runtime descriptor accepts the empty reason as one successful skip. This covers raw single-file, same-package, external-test, honest test-only, filtered, coordinator-run retained, and later direct retained-binary execution, including an active-test call reached through production package code. Production source still contributes no test descriptor. The result has no diagnostic or harness error, uses the existing blank-after-colon skip line, increments only skipped accounting, and permits later selected tests to continue. - **Go-like package:** source roles, descriptor order, initialization, declared names, and canonical package and variant identities do not change. A runtime reason is result data, never identity. - **Go-like import:** `import test`, exact dotted dependency resolution, graph edges, initialization, qualifier binding, and unused-import behavior do not change. No reason byte becomes import, graph, action, symbol, `.wwi`, artifact, publication, or persistence identity. #### Lifecycle, parity, proof, and formats Filename and source eligibility, selected-file order, and test-role classification are unchanged. An empty reason has no loader representation. Graph nodes, edges, actions, ordering, product scheduling, generated descriptors, compiler/assembler/archiver/linker operation, and private/public output naming remain unchanged. Existing source-content invalidation rebuilds affected runtime/test actions; there is no test-result cache. At runtime, only the valid zero-length skip classification changes. Passes, nonempty skips, assertion failures, signals, expected abort, premature clean exit, ordinary abort, timeout ownership, process groups, descendant cleanup, and the existing per-test process boundary retain their current owners and behavior. An empty skip emits no diagnostic. Oversized reasons remain harness errors, skip outside an active test still aborts, and all build, producer, runtime, publication, and cleanup diagnostic channels and precedence remain unchanged. Affected private and retained test executables change because their shared runtime changes; comparable Cstage and WWstage executables must remain byte-identical. `-c`, running `-o`, guarded installation, destination modes and names, exact null discard, private execution, and publication order are unchanged. A successful empty skip reaches the existing success-publication path. Producer, other runtime, and publication failures retain their existing failure classification, cold no-partial-publication guarantee, and warm preservation of committed generations and prior public bytes. Persistence keys and schemas do not change. Existing content invalidation, warm action reuse, relink, commit, rollback, parallel product isolation, capture ownership, cancellation, interruption escalation, owned-child cleanup, and transaction/scratch cleanup remain unchanged. No active `.new`, `.install`, `.wwtxn.*`, adjacent `.sepwork`, capture, result, scratch, or tool-stage transaction residue may remain outside an explicitly retained or recipe-owned boundary. After the change, both stages directly ran the fixed-path two-test probe with status 0 and empty stderr. They emitted the same empty-reason skip line, ran the later passing test, reported one pass, one skip, zero harness errors, complete 2/2 accounting, and the ordinary package `ok` result. Empty-only and pass-only filters each succeeded, and list mode still printed both names without running them. Both `test -c -o` invocations had empty streams and produced byte-identical 112,861-byte mode-0755 executables with SHA-256 `257d05a99e920875e9d131ce18e7f11592179802fc6f864fc136ebf618d4a88c`. Both retained executables then ran directly with status 0, identical empty stderr, and identical skip/pass/accounting output. The WW-native `empty_skip_reason_is_a_successful_skip` observer passed after rebuilding `out/bin/test_package`. Its dynamic sources directly prove both-stage status and stdout/stderr parity for raw single-file, same-package, external, and honest test-only descriptors; an active-test call through production code; later-test continuation; a nonempty-skip control; empty-only and pass-only filters; list nonexecution; cold and warm work; compile-only and running retention; byte-identical retained and ordinary `import test` executables; direct retained execution; unchanged outside-active abort; the unchanged 4,094-byte oversized-reason harness error; and transaction/residue cleanup. The complete focused `make -j1 JOBS=1 test-package` owner then passed all 53 observers with zero failures, skips, or harness errors. All ordered full gates then passed serially after the final executable production and proof changes: 1. `make -j4 JOBS=4 test` 2. `make -j4 JOBS=4 test-commit` 3. `make -j4 JOBS=4 test-byteid` 4. `make -j1 JOBS=1 test-bootstrap` 5. `make -j1 JOBS=1 test-platform` 6. `make -j1 JOBS=1 test-all` Every command exited zero. The byte-identity gates compared 161 language files and 1,421 data fixtures with zero pinned-divergent fixtures; bootstrap retained the `ww2 == ww3 == ww4` fixed point and five-tool WWstage round-trip byte identity; and the platform dynamic-link artifact remained Cstage/WWstage byte-identical at 8,464 bytes. A final read-only review produced two wording-only corrections: the pinned `Skip`/`SkipNow` description was split precisely, and the warm observer comment was limited to persisted-work execution rather than claiming unmeasured action reuse. With production and executable proof logic unchanged, the exact final observer source then passed `make -j1 JOBS=1 test-package` again: all 53 tests passed with zero failures, skips, or harness errors. No format bump. Build workdir format remains `18`, test workdir format remains `19`, semantic storage format remains `3`, and no test-result cache is introduced. ### 11.48 Implemented selector-only effective import bindings Pinned Go's applicable semantic rule is that an imported package's effective name denotes a package-name object, not a value or type, and that object may be used only to qualify a selector. A bare value occurrence is rejected as `use of package BINDING not in selector`; a bare type occurrence is rejected as `BINDING (package name) is not a type`. A bare occurrence does not mark the import used, while a selector does. These rules and diagnostics are **behavior directly implemented or asserted by pinned Go**. The rule honestly applies within WW's local, dotted-import, manifest-free model. WW already resolves every ordinary import to an effective default or explicit file-local qualifier and already represents qualified value and type selectors. Treating that existing qualifier as a package-name object closes a checker hole without adding quoted, grouped, dot, generalized, network, module, manifest, registry, or source-expression import machinery. Applying Go's package-name-object rule to WW's already representable import binding is **behavior derived from the pinned implementation**. #### Pinned evidence and fact classification The sole semantic authority is official Go 1.26.5 at `c19862e5f8415b4f24b189d065ed739517c548ba`: - [`ident` in `cmd/compile/internal/types2/typexpr.go`, lines 18–60](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/typexpr.go#L18-L60) resolves an identifier to its object and, in a type context, rejects an object that is not a type name as `NAME (KIND) is not a type`; - [the package-name value branch in that file, lines 89–92](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/typexpr.go#L89-L92) rejects a package name outside a selector as `use of package NAME not in selector`; - [`objectKind` in `cmd/compile/internal/types2/object.go`, lines 675–680](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/object.go#L675-L680) names a `PkgName` object's kind `package name`; - [selector checking in `cmd/compile/internal/types2/call.go`, lines 672–735](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/call.go#L672-L735), especially lines 681–691, admits a package name in the selector position and marks that exact package-name object used; - [import declaration in `cmd/compile/internal/types2/resolver.go`, lines 248–340](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L248-L340) creates the `PkgName` in file scope, and [`unusedImports`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740) diagnoses each nonblank package-name object not marked by a selector; - [compiler diagnostic sorting in `cmd/compile/internal/base/print.go`, lines 70–92](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/base/print.go#L70-L92) preserves stable source-position ordering; and - [binary-expression checking in `cmd/compile/internal/types2/expr.go`, lines 788–802](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/expr.go#L788-L802) checks both operands before returning for either invalid result, so two bare package-name operands retain two independently owned diagnostics. Those source branches are **behavior directly implemented or asserted by pinned Go**. Official assertions are [`test/fixedbugs/issue11361.go`, lines 7–11](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/fixedbugs/issue11361.go#L7-L11), which pairs an unused import with its bare package-value error; [`src/internal/types/testdata/check/builtins0.go`, lines 613–617](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/builtins0.go#L613-L617), which rejects a package name passed as a value; and [`src/internal/types/testdata/check/decls1.go`, lines 45–73](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/decls1.go#L45-L73), especially line 66, which asserts `math (package name) is not a type`. From those pinned mechanisms it follows that a bare-only named import receives both its unused-import diagnostic and its context-specific package-name diagnostic; a legal selector removes only the unused diagnostic and never excuses a distinct bare occurrence; an explicit alias supplies the displayed name; and a sibling file without its own binding follows ordinary name lookup. Those conclusions are **behavior derived from the pinned implementation**. #### Fresh four-axis audit and direct pre-fix measurements The fresh audit also confirmed multiple named source operands, explicit `*_test.ww` build operands, shared top-level test-process state and fatal-abort behavior, Go's regular-expression `-run` matching, and lexical shadowing of import bindings as applicable but unselected differences. Ordinary directory production selection was aligned. Grouped, quoted, and dot imports remain inapplicable to WW's deliberately narrower syntax. Those classifications are audit conclusions, not claims that this slice closes the unselected behavior. Before this slice, the following observations were **directly measured WW behavior**. With a dependency declared `package wire` and exporting a value and type, both stages accepted legal `wire.Value` and `wire.Number` controls and produced byte-identical 8,201-byte executables with SHA-256 `7fb0e95229aa22714d880070388ee5169697543076536267a8c709429cce0fcb`; both ran with status 41. A bare-only value caused only the generated-unit unused-import diagnostic in each stage. Once a legal selector marked the import used, Cstage let a separate bare value reach the linker as `undefined reference to 'wire'`, while WWstage let it reach code generation as `cgident: unresolvable identifier (rule 7)`. An explicit alias reproduced the same stage split using that alias. Reversing occurrence order or adding a second bare occurrence did not restore checker ownership. A bare type plus a legal selector was reported by both stages as `unknown type 'wire'`, rather than the pinned package-name diagnostic. With no selector, Cstage also retained the unused-import error, while WWstage emitted only the unknown-type error. A sibling source that did not import `wire` let a bare value reach the linker or code generator rather than following ordinary undefined-name checking. Blank-import controls did follow ordinary undefined lookup, missing targets retained missing-package precedence, and the valid qualified/blank control retained artifact-byte and runtime parity. All cold failed work directories examined were empty and no output was published. The same checker escape was measured in same-package, external-test, honest test-only, production-test, and imported-dependency paths: the test coordinator reported `FAIL`, but Cstage failed in the linker while WWstage failed in code generation. These status, stream, artifact, and cleanup results are **directly measured WW behavior** from the pre-change Cstage/WWstage probes; they are not attributed to Go. The directly measured pre-fix result across the permanent axes was therefore: - **Go-like build:** legal selector controls loaded, compiled, linked, published, and ran byte-identically, but a bare package name escaped semantic checking and failed at different backend phases; - **Go-like test:** every applicable generated test source role reached the ordinary package failure result, but its checker diagnostic and failure phase differed between stages; - **Go-like package:** effective qualifiers were already source-local during legal selector resolution, but sibling and bare lookup could escape that source-local package-name boundary; and - **Go-like import:** unused accounting recognized some selector uses, but a bare import binding was not consistently classified as a non-value, non-type package-name object. #### Ownership and complete four-axis contract The true semantic owner is identifier and type-name resolution in the Cstage and WWstage semantic checkers. The checker must distinguish a package-name object belonging to the current source from ordinary lexical or package-scope objects before generic undefined, type, code-generation, or link recovery. A selector remains the only construct that consumes such an object and marks its import used. A bare type name must not accidentally mark the import used. Both implementations must produce the same normalized diagnostics at the same source positions and retain ordinary undefined or unknown-type behavior when the current file has no binding. - **Go-like build:** every selected source is rejected during semantic checking before compiler output, assembly, archive, link, or installation when it contains a bare package-name object. Legal selectors retain the existing build graph, actions, artifact bytes, runtime result, and publication rules. - **Go-like test:** production, same-package, external-test, and honest test-only sources use the same checker rule. Rejection precedes test-process construction and execution; discovery, filters, descriptors, result accounting, fatal/skip behavior, timeouts, and process cleanup do not change. - **Go-like package:** the binding remains owned by exactly its source file. Declared package names, canonical package and variant identity, selected source membership, exported declarations, initialization, and symbol naming do not change. - **Go-like import:** default and explicit named bindings become consistently selector-only package-name objects. Selectors alone satisfy unused-import accounting. Blank imports create no binding, rejected effective `init` imports install none, and missing-target resolution keeps precedence. #### Lifecycle, parity, proof, and formats Loading and source eligibility, filename ordering, package-clause validation, canonical dotted resolution, contextual local/vendor expansion, source-role classification, and graph-edge construction remain unchanged. The diagnostic is a property of an already resolved file-local binding; physical directories remain loader and presentation metadata and never acquire package, import, graph, action, artifact, symbol, `.wwi`, publication, or persistence identity. Semantic rejection occurs within the compiler action before code generation, so no assembler, archiver, linker, test runtime, or installer may run for the invalid action. Diagnostic source order and precedence must remain stable: missing-package, invalid effective-`init`, blank-no-binding, import collision, and ordinary undefined-name paths keep their established owners; a valid binding receives the exact package-name diagnostic and, unless a selector separately used it, its independent unused-import diagnostic. Repeated invalid bare occurrences are diagnosed independently. Cold rejection must publish no executable, archive, interface, retained test binary, or partial semantic action. Warm rejection must preserve the previous public product and complete committed work generation byte-for-byte. A later valid request must recover through existing invalidation and reuse rules. Neither rejected source text nor its physical directory may create a new identity or persistence key. Valid controls must retain comparable Cstage and WWstage diagnostic and artifact-byte parity. The invalid consumer's compiler action starts and rejects during semantic checking, before its code-generation or downstream producer boundary. Already valid dependency producers may also have completed before that rejection. Assembler, archiver, linker, installer, test-runtime, and runtime-failure paths for the invalid consumer are therefore unreachable. Existing producer/runtime failure, rollback, publication transactions, parallel-product isolation, concurrent-request locking, cancellation, interruption escalation, child ownership, and descendant cleanup remain unchanged for other actions. Rejection must remove request-owned stages and leave no active `.new`, `.install`, `.wwtxn.*`, adjacent `.sepwork`, capture, result, scratch, or tool-stage transaction residue. The WW-native `bare_import_bindings_require_selectors` observer is required to prove exact cross-stage status and normalized diagnostic parity for bare value and type contexts, explicit aliases, selector order, repeated occurrences, unused accounting, sibling-file isolation, blank/`init`/missing controls, ordinary and imported builds, builtin-spelled package callees (`len`, `size`, and `align`), nested value/type contexts, and every applicable test source role. In particular, parser-shaped `size`/`align` type arguments must keep type checking after the callee is classified as a package-name object and must never escape through generic internal-expression recovery. The observer must also prove valid artifact-byte/runtime parity, cold empty rollback, warm prior state preservation, invalidation and recovery, and residue cleanup. Broader producer/runtime failure, concurrency, interruption, and descendant-process behavior retain their existing owners because this slice adds no such boundary. These are proof requirements; validation and final post-change byte measurements are recorded only after they are run. No format bump. Build workdir format remains `18`, test workdir format remains `19`, semantic storage format remains `3`, and no test-result cache is introduced. ### 11.49 Implemented lexical shadowing of import bindings An effective nonblank import qualifier is a file-local package-name object, not a reserved spelling. An ordinary closer lexical binding may shadow it. Each occurrence resolves to the nearest visible object: a selector before the local declaration denotes the import and satisfies that import's use accounting; the same spelling after a parameter, local, tuple-local, loop/range binder, or match-arm binder denotes that closer binding. Leaving the nested scope restores the import binding. A selector consumes an import only when its receiver actually resolves to that import's package-name object. A selector whose receiver is a local value neither consumes nor resurrects the same-spelled import. This includes explicit aliases and qualifiers spelled like builtins. This is lexical binding recovery, not a new import form or an identity rule. Blank imports and rejected effective-`init` imports still install no binding; an unresolved target still fails during resolution before checker binding semantics. WW's existing `for ... else` behavior has no Go counterpart and is unchanged. #### Pinned Go evidence and fact classification The sole semantic authority is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - the language specification defines imports as package objects with file-block scope, and defines parameter/body/local declaration points, nested scopes, and inner-declaration shadowing ([`doc/go_spec.html`, lines 2160–2174 and 2190–2233](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/doc/go_spec.html#L2160-L2233)); - `types2` constructs a file scope and `PkgName`, then resolves objects from the innermost scope outwards ([`cmd/compile/internal/types2/resolver.go`, lines 223–335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L223-L335), [`check.go`, lines 73–94](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/check.go#L73-L94)); - parameter and local declaration timing is implemented in [`signature.go`, lines 143–180](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/signature.go#L143-L180) and [`assignments.go`, lines 525–602](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/assignments.go#L525-L602); - selector checking marks an import used only after its receiver resolves to a `PkgName`; bodies are processed before unused imports are diagnosed ([`call.go`, lines 672–692](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/call.go#L672-L692), [`check.go`, lines 496–523](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/check.go#L496-L523), [`resolver.go`, lines 706–740](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L706-L740)); and - official fixtures compile a selector before a later local, retain that declaration-point distinction, and show parameter shadowing ([`test/fixedbugs/bug129.go`, lines 8–13](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/fixedbugs/bug129.go#L8-L13), [`issues0.go`, lines 16–23](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/issues0.go#L16-L23), [`bug107.go`, lines 8–15](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/fixedbugs/bug107.go#L8-L15)). Those specification, resolver, selector-use, declaration-point, and fixture facts are **behavior directly implemented or asserted by pinned Go**. That a WW occurrence before a local consumes the import, an occurrence after it sees the local, a nested scope restores the import on exit, aliases and builtin-spelled qualifiers follow the same rule, and a local selector does not consume the import is **behavior derived from the pinned implementation**. The behavior honestly applies to WW's existing file-local dotted bindings and representable lexical scopes without introducing Go's modules, manifests, quoted/grouped/dot imports, registry, cache, network resolution, or source build expressions. #### Fresh four-axis audit and direct pre-fix measurements The fresh simultaneous audit classified multiple named source operands as a different, applicable build/package slice; explicit `*_test.ww` build operands as a different, applicable build/source-selection slice; shared top-level test process state and fatal-abort topology as different, applicable test slices; and Go-compatible regular-expression `-run` matching as a different, applicable test slice. They remain open and unselected: each needs a wider true-owner change. Grouped, quoted, and dot imports are inapplicable to WW's deliberately narrow import grammar. No fresh pinned evidence reopened a completed section through §11.48. Before this slice, all following results were **directly measured WW behavior**: - a directory build containing a real package selector followed by a legal `let shadowmod` failed in both stages before publication; Cstage emitted positioned 155-byte stderr (SHA-256 `13cfac9494a1f6c0ee958d3b74ecfe8b0efe2a685f31a8a1771fda3fa0af1b02`), while WWstage emitted unpositioned 76-byte stderr (SHA-256 `298e4991ca9900ef32499762f8ae9abb8ace07c3e672dc66db1e911a8de62b75`). Both had empty stdout, no output, and empty precreated workdirs; - same-package and external test shadows failed before descriptor execution; both emitted exactly `FAIL\n`, published/retained nothing, and left no work entry. Cstage stderr was 277 bytes (SHA-256 `ac850802e5911f53c3e64be2ab55e1f3442438eadab35a40f63ddac869337e4e`), WWstage was 186 bytes (SHA-256 `a1229bd19628e5dc909a0bcb848c30cc1dbdf9d370f21ed51e79489c06abcad0`); - after a genuine selector, `let shadowmod: i32 = 1; return shadowmod.say()` produced only the shadow prohibition in Cstage, but WWstage additionally cascaded through `calling non-function` and `asserttyped: dot`; and - an otherwise-unused import with only local `shadowmod.n` produced the shadow prohibition rather than unused-import in both stages, proving the former syntax-only use pass falsely consumed the import. Legal no-shadow controls built, published byte-identical executables (SHA-256 `7b710cf0973821cec430878d1f90de64485438510512561263c1a16b367c3c78`), and exited 42. The direct probes also covered parameter, local, nested, explicit-alias, selector-before/after, imported-dependency, same-package, external-test, and honest test-only paths; both stages rejected every legal shadow. Thus the pre-fix difference was legal-source rejection, false unused-import accounting, and stage-divergent downstream recovery. #### Ownership and complete four-axis behavior The true owners are the Cstage semantic checker in `cmd/wcc/check.c`, its self-hosted twin in `selfhost/cmd/wcc/check.ww`, and the latter's `selfhost/cmd/wcc/cgenexpr.ww` local-versus-imported-enum fast path. They remove the import-shadow prohibition; resolve use accounting through isolated temporary lexical scopes rather than merely selector spelling; preserve declaration timing; and gate dotted package/enum shortcuts on the visible binding. The Cstage code generator already follows checker/local stamps and is proved rather than redefined. Parsers, loader/source selection, drivers, coordinator, canonical resolution, graph/action construction, assembler, archiver, linker, runtime, publisher, and persistence records are not owners. - **Go-like build:** raw, directory, and imported programs with legal shadowing now pass checking, build through unchanged actions, publish normally, and run the local value/field/function-pointer behavior. A genuinely invalid local selector fails during checking before code generation or downstream tools. - **Go-like test:** production called by test, same-package, external-test, honest test-only, filtered, retained, and directly retained products use the same rule before execution. Discovery, filters, descriptors, process state, fatal/skip behavior, timeout, retention, and cleanup are unchanged. - **Go-like package:** import binding remains file scoped; ordinary local scopes nest within it, and sibling source files remain independent. Declared names, source roles, package/variant identities, exported declarations, initialization, symbols, and selected membership do not change. - **Go-like import:** the nearest visible object wins. Only a selector whose receiver is the visible package-name object satisfies unused-import accounting; local field selectors do not. Default/explicit aliases, blank imports, effective-`init`, missing-target precedence, canonical dotted identity, contextual local/vendor mapping, visibility, cycles, and direct graph edges retain their existing semantics. #### Lifecycle, parity, proof, and formats Filename/platform/test-role eligibility, byte-sorted source selection, package clauses, source IDs, loading, and resolution remain earlier owners. Shadowing does not add/remove an already-resolved direct import edge, rekey actions, or change action order, variants, initialization dispatch, linker symbols, `.wwi` ownership, artifacts, publication, or persistence identity. Physical directories remain loader/runtime/presentation metadata, never canonical package, import, graph, action, artifact, symbol, publication, or storage identity. The lexical-aware prepass keeps source-position diagnostic ordering. It removes every `shadows imported module` diagnostic while preserving missing target, invalid effective-`init`, blank/no-binding, collision/redeclaration, and selector-only package-name diagnostics. An otherwise-unused import is reported before a later invalid local selector according to source position; local invalid dots reject with the same positioned recovery stamp in both stages and cannot cascade into C/WW code generation, assembler, or linker diagnostics. Valid shadowing reaches ordinary compiler, assembler, archiver, linker, and runtime paths. The representative package matrix proves byte-identical Cstage/WWstage unit, interface, assembly, object, archive, initializer, and published executable artifacts; every test source role proves public binary parity, and the retained case proves retained-binary parity. A cold invalid action creates no public/retained/interface/archive/object/executable artifact and no `.new`, `.install`, `.wwtxn.*`, adjacent `.sepwork`, capture, result, or request scratch. A warm edit that makes an import unused while also introducing an invalid local selector preserves the prior committed generation and public product byte-for-byte; exact restoration uses ordinary invalidation/reuse and cannot leave poisoned state. Existing producer/runtime failure, late publication failure, rollback, concurrency, interruption, process-group ownership, and cleanup remain their existing owners because this checker slice adds no process, lock, transaction, or shared runtime state. The WW-native `lexical_import_bindings_shadow_normally` package observer and the tool-suite `paramshadow_lexical_bindings` fixture matrix jointly prove selector before local, self-shadowing initializer, parameter/let/tuple-let/ ordinary-for/range/match-arm declaration timing, all annotated tuple types before any tuple binder, nested restoration, aliases and builtin-spelled qualifiers, local struct/pseudo/function-pointer fields, imported-enum name collisions, local dotted type/value rejection, unused accounting, and sibling-file isolation. The package observer also covers raw and directory builds, imported dependencies, every applicable test role, filtered and retained/direct-retained execution, normalized diagnostic parity, valid artifact/runtime parity, cold cleanup, warm preservation/restoration, and residue absence. Blank/effective-`init`/missing-target behavior is unchanged and remains proved by the immediately preceding focused observers. Go has no range-loop `else` clause. That WW-only extension is therefore inapplicable to this pinned-Go slice and was not redefined: the pre-existing Cstage behavior keeps a range binder visible in `else`, whereas WWstage restores the outer scope before `else`. Each stage's import-use prepass deliberately matches its own live checker there; the cross-stage extension difference remains open and is not presented as lexical-shadow parity proved by this slice. No serialized format changes. This alters lexical resolution of source bytes already present in the existing action vouchers and adds no action-key, graph, artifact-layout, harness-protocol, cache, database, or publication field. Build workdir format remains `18`, test workdir format remains `19`, semantic storage format remains `3`, and no test-result cache is introduced. ### 11.50 Implemented named-source leading-dot/underscore eligibility An explicitly named raw `.ww` source now observes the same unconditional basename exclusion as a named `.go` source in Go 1.26.5. This closes the gap in WW's existing single-source command route: a final requested basename beginning `.` or `_` is not a package source, even though named sources otherwise bypass directory-only target-suffix selection. Directory selection already enforced this rule and remains unchanged. #### Pinned Go evidence and applicability The reference is official Go 1.26.5 at commit `c19862e5f8415b4f24b189d065ed739517c548ba`: - `PackagesAndErrors` recognizes an existing `.go` operand and routes the complete named list to `GoFilesPackage` ([`cmd/go/internal/load/pkg.go`, lines 2903–2918](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2903-L2918)). `GoFilesPackage` enables `UseAllFiles`, presents only the named `FileInfo` entries through a synthetic directory, and loads one command-line package ([lines 3244–3315](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L3244-L3315)). - `go/build.Import` passes each synthetic entry through `Context.matchFile` ([`go/build/build.go`, lines 886–914](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L886-L914)). `matchFile` rejects a name beginning `_` or `.` before extension, target suffix, open, imports, or build constraints; that branch precedes the `UseAllFiles` condition ([lines 1438–1509](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1438-L1509)). A package with no remaining source category returns `NoGoError` ([lines 1076–1082](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1076-L1082)); the command loader presents the case as `no Go files` ([`cmd/go/internal/load/pkg.go`, lines 250–270](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L250-L270)). - Build reports load errors before installation/action construction ([`cmd/go/internal/work/build.go`, lines 697–728](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L697-L728)). Test uses the same loader ([`cmd/go/internal/test/test.go`, lines 703–719](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L703-L719)) and turns its error into package setup failure before constructing a runnable ([lines 1015–1050](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/test/test.go#L1015-L1050)). - Official command testdata explicitly records that `_cgo_yy.go` named on the command line is ignored and permits the exact `no Go files` result ([`cgo_bad_directives.txt`, lines 11–23](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/cgo_bad_directives.txt#L11-L23)). `import_ignore.txt` independently proves a dot file contributes no import ([lines 1–11](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/import_ignore.txt#L1-L11)). The rule honestly applies to WW's local literal `.ww` operand. It adds no module, manifest, registry, network, generalized import, or build-expression surface. This section is deliberately bounded to the existing single raw source target. Multiple named sources as one package and visible `*_test.ww` exclusion from `ww build` remain separate open semantics; when a future source-set loader admits multiple names, it must apply this same rule to each requested basename. #### Source, package, and import ownership The twin public drivers own one allocation-free operand predicate after existing CLI-shape checks and a successful requested-path `Stat`, but before logical resolution or graph entry. It requires an original spelling ending exactly `.ww`, then examines only the final requested basename. A hidden parent containing visible `main.ww` does not exclude the named source. A requested hidden symlink spelling is excluded even when its target is visible or non-regular, while a visible requested spelling remains eligible even when its target basename is hidden. This follows the `FileInfo.Name` seen by Go's synthetic named-file directory: Unix `Stat` follows the target but fills `Name` from the requested path ([`os/stat_unix.go`, lines 28–38](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/stat_unix.go#L28-L38), [`os/stat_linux.go`, lines 13–30](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/stat_linux.go#L13-L30)). Physical target paths do not become identity. Prefix exclusion precedes every later classifier. `_main_test.ww` and `.main_test.ww` are absent before production/test partitioning. A hidden `_main_windows.ww` is absent, but a visible `main_windows.ww` named directly remains eligible because the named-file analogue uses `UseAllFiles`; directory platform filtering is unchanged. Logical operands without a `.ww` suffix, directory and recursive requests, imports, and `ww run` retain their existing routes. An excluded operand creates no package clause, declaration, production/test variant, or top-level state. Its bytes are not decoded or parsed: malformed UTF-8, NUL, BOM, missing/invalid package clauses, late imports, missing imports, unused imports, cycles, `internal`/vendor rules, and checker diagnostics cannot resurrect it or outrank selection. It contributes no qualifier, import-use obligation, edge, canonical dotted identity, initializer, or link closure. The lexical parent printed by the diagnostic is presentation metadata only and is never package, import, graph, action, symbol, `.wwi`, artifact, publication, or persistence identity. #### Observable command and lifecycle behavior `ww build HIDDEN.ww` exits 1 with empty standard output and `ww: PARENT: directory contains no WW package sources` on standard error. An ordinary explicit running `ww test HIDDEN.ww` adds its established exact command-owned `FAIL` line on standard output; compile-only and assembly-only test requests do not. With no slash, `PARENT` is `.`, a root child uses `/`, and otherwise it is the requested lexical bytes before the final slash. CLI flag/path-length errors and the existing raw-test directory-only package-option shape keep their precedence. A failed requested-path `Stat` retains ordinary target/logical resolution; for an existing non-directory raw operand, no-source selection precedes logical resolution, output-destination preflight, and all source, producer, publication, and runtime diagnostics. Exact `/dev/null` does not suppress the load failure. No root/dependency action, test support, generated main, compiler, assembler, archiver, linker, harness, test child, or program process starts. Cold rejection creates no default or explicit output, workdir, adjacent `.sepwork`, unit, `.wwi`, assembly, object, archive, init artifact, binary, status, stage, capture, result, transaction, or private temporary directory. Warm rejection starts no transaction and preserves every prior work-artifact and public/retained byte. It leaves no `.new`, `.install`, `.wwtxn.*`, or recovery residue. Producer, runtime, publication-only, cleanup-only, signal, timeout, and descendant semantics for visible inputs are unchanged. The predicate is request-local and creates no shared state, process group, lock, or interruption owner, so overlapping hidden and visible requests remain isolated. Cstage and WWstage must agree byte-for-byte on status, stdout, stderr, and complete artifact absence; representative visible named sources retain binary and semantic-artifact identity. The focused native `named_source_prefixes_are_ignored` observer owns both prefixes, build/test and compile-only paths, prefix-before-test/platform precedence, requested symlink spelling, hidden-parent/visible-basename and wrong-platform controls, unread malformed/import bytes, cold cleanup, warm preservation/restoration, residue, and stage parity. No serialized format changes. Build workdir format remains `18`, test workdir format remains `19`, semantic storage format remains `3`, and there is no test result cache. ### 11.51 Implemented explicit named test-source build omission A single existing raw `ww build` operand whose requested final basename ends exactly `_test.ww` is now a test-only named source. WW syntax-observes only the package clause and its initial contiguous import section, preserves any read/header diagnostic, then omits the valid test-only root before logical resolution or action construction. This is deliberately distinct from the leading-dot and underscore rule in 11.50: `_test.ww` reaches that earlier exclusion, whereas a visible `x_test.ww` reaches this test-only omission. #### Pinned authority, tests, and applicability - **behavior directly implemented or asserted by pinned Go** — official Go 1.26.5 commit `c19862e5f8415b4f24b189d065ed739517c548ba` recognizes an existing non-directory named `.go` operand in `PackagesAndErrors` ([`cmd/go/internal/load/pkg.go`, lines 2903–2918](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L2903-L2918)), builds its synthetic command-line package with `UseAllFiles` ([lines 3244–3315](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L3244-L3315)), and classifies `_test.go` separately from `GoFiles` ([`go/build/build.go`, lines 930–1036](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L930-L1036)). `UseAllFiles` bypasses ordinary target and build-expression rejection, but not that test-file classification ([lines 1438–1509](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1438-L1509)). - **behavior directly implemented or asserted by pinned Go** — on a successfully scanned header, `readGoInfo` reads the initial package/import header and one stop byte, then removes that byte before parsing; on header syntax recovery it deliberately drains the remaining source ([`go/build/read.go`, lines 265–315](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/read.go#L265-L315)). Every raw NUL reached by its reader is a read error ([lines 71–89](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/read.go#L71-L89)); `parser.ImportsOnly` stops before ordinary declarations ([`go/parser/parser.go`, lines 2887–2923](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/parser/parser.go#L2887-L2923)). Thus a package or initial-import header error precedes omission, while a later declaration/body error does not become an ordinary-build error. - **behavior directly implemented or asserted by pinned Go** — ordinary initial loading does not recursively resolve test imports ([`cmd/go/internal/load/pkg.go`, lines 350–358](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L350-L358)); `go/build` records their metadata at `go/build/build.go:1037–1040`. Build checks loader errors first and then omits a test-only root before output/action construction ([`cmd/go/internal/work/build.go`, lines 459–559 and 731–745](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L559)). - **behavior directly implemented or asserted by pinned Go** — related official anchors are `go/build/build_test.go:382–421` (`TestMatchFile`), `go/build/build_test.go:812–831` (`TestDirectives` and `XTestDirectives`), `go/build/read_test.go:17–73,120–159,165–249` (header boundary, NUL, and syntax recovery), `cmd/go/testdata/script/test_relative_cmdline.txt:1–49`, and `cmd/go/testdata/script/build_test_only.txt:1–18`. The pinned official repository has no script that directly invokes `go build NAME_test.go`; the exact named-build result below is derived from its pinned loader and action ordering, not presented as an unanchored direct script assertion. - **behavior derived from the pinned implementation** — one valid named test source produces no build action. No effective `-o` and exact `/dev/null` succeed silently; a non-directory output reports `ww: no packages to build\n`; an existing or trailing-slash output directory reports `ww: no main packages to build\n`. Header loading occurs before those empty-selection branches. - **behavior derived from the pinned implementation** — the pinned body boundary is byte-sensitive: an ordinary non-`i` stop byte, a first malformed UTF-8 byte, or a later BOM byte is excluded, while a reached NUL and an unterminated comment remain load errors; a following byte `i` is attempted as another import. WW applies the corresponding rule at its lexical `import` boundary: it never lexes the first ordinary body token, but preserves NUL and comment diagnostics encountered while skipping header trivia. The rule honestly applies to WW's local, manifest-free literal `.ww` model: `*_test.ww` already means test source for directory selection and `ww test`. It introduces no module, manifest, registry, lock, network resolver, cache, generalized import grammar, source build expression, or test-result cache. #### Source and identity ownership - **behavior directly implemented or asserted by pinned Go** — named-source package construction presents `Stat`-derived file information through its synthetic directory. The operand spelling remains the file name presented to selection, even though `Stat` follows a symlink. - **behavior derived from the pinned implementation** — the twin true owners are `cmd/ww/main.c::do_build` and `selfhost/cmd/ww/main.ww::dobuild`, after the existing hidden-prefix check and before `resolve_module` / `resolvemodule`. A requested visible non-directory spelling ending `_test.ww` is classified from that spelling; a symlink to a directory remains a directory request. The finite-stream header reader is not a regular-file restriction: a supplied finite FIFO is read as a source, while an unreadable entry reports its header read failure. Physical parent directories and symlink targets remain loader metadata, never canonical package or import identity. - **behavior derived from the pinned implementation** — platform-looking visible names such as `x_windows_test.ww` remain test-only named sources. Multiple named sources, logical operands without `.ww`, directories, recursive requests, `ww run`, and all visible non-test raw operands retain their prior routes. In particular, this does not implement Go's multiple named-source package collection. - **behavior derived from the pinned implementation** — the header observation is discarded after classification. It creates no canonical package, command-line package representative, dotted import identity, qualifier, symbol namespace, `.wwi`, action, archive, publication, or persistence key. Initial import syntax is checked solely for load-error precedence; omitted test-source imports are not resolved and create no graph edge or action. #### Build, test, package, and import effects - **behavior directly measured WW behavior** — before this change, both stages compiled, linked, published, persisted, and ran a valid visible `only_test.ww`; `ww build -w WORK -o OUT only_test.ww` exited 0 with empty streams, a byte-identical mode-0755 executable, populated work state, and runtime status 19. A missing test-only import likewise reached ordinary import resolution. - **behavior derived from the pinned implementation** — post-contract build behavior is an empty production selection after a valid header: no compiler, assembler, archiver, linker, generated main, test harness, test child, or program process starts. `-S` follows the same no-action rule. No runtime result can occur. - **behavior derived from the pinned implementation** — package behavior is confined to the transient header check; no production/test variant or package action remains. Import behavior is likewise confined to syntax; missing test-only dotted imports, late imports, body syntax/type errors, and runtime faults cannot enter the production graph. - **behavior derived from the pinned implementation** — test behavior is an explicit non-effect. Raw `ww test`, `ww test -c`, and `ww test -S` continue to select named test files. Directory and recursive `ww build` already exclude selected test sources and remain unchanged. #### Diagnostics, artifacts, and lifecycle - **behavior derived from the pinned implementation** — CLI-shape and multiple-operand delegation retain their prior precedence; 11.50 prefix exclusion precedes this header reader. Header read/package/initial-import diagnostics precede output policy. A first ordinary malformed UTF-8/BOM body byte is excluded, while a reached NUL or unterminated header-trivia comment is a header diagnostic. Once the header is valid, no unresolved import, graph, producer, linker, or runtime diagnostic may surface. Both stages use the same header boundary and must produce byte-identical status, stdout, and stderr. - **behavior derived from the pinned implementation** — cold no-action success creates no default/explicit output, output directory, `.wwi`, unit, assembly, object, archive, init product, `.sepwork`, workdir, stamp, transaction, capture, result, or private build temporary. Output-policy diagnostics also create none of those products. - **behavior derived from the pinned implementation** — a warm request starts no transaction, mutation, invalidation, reuse check, timestamp refresh, or producer. Existing output, sidecar, workdir and artifacts remain byte-identical on success and failure; no `.new`, `.install`, `.wwtxn.*`, backup, or recovery residue remains. Restoring a visible non-test source reuses prior valid warm state by the unchanged ordinary route. - **behavior derived from the pinned implementation** — no action means no publication, rollback work, producer/runtime failure path, shared lock, or child process. Concurrent Cstage/WWstage no-action and header-diagnostic requests are isolated. Interruption during header reading leaves no owned persistent state; after a valid header there is no child or publication window to clean up. Every reader closes its descriptor and releases request-local storage before return. - **behavior derived from the pinned implementation** — focused proof covers valid, malformed-header, missing-test-import, wrong-platform, symlink and finite-stream operands; default/file/directory/null/assembly output modes; cold/warm preservation; trace-proven tool and runtime absence; rollback, interruption, concurrency, cleanup, complete per-stage work preservation, and Cstage/WWstage semantic-artifact parity. The complete per-stage snapshot includes `.wwtool.ww`; cross-stage comparison excludes only that intentionally different producer binary snapshot. Unaffected visible production controls retain byte-identical outputs. No serialized format changes accompany this omission. Build workdir format remains `18`, test workdir format remains `19`, semantic storage format remains `3`, and the slice adds no cache or persistent record. ### 11.52 Implemented `.ww`-spelled directory build routing An existing local literal passed to `ww build` whose requested final basename ends `.ww` is a directory-package request when ordinary `stat` reports a directory. This includes a direct directory named `.ww` and a visible `_test.ww` symlink to a directory. The suffix does not turn the directory into a raw source and does not trigger the non-directory test-source omission in 11.51. #### Pinned authority and applicability - **behavior directly implemented or asserted by pinned Go** — official Go 1.26.5 commit `c19862e5f8415b4f24b189d065ed739517c548ba` implements symlink-following `Stat` in `cmd/go/internal/fsys/fsys.go:633–638`. `PackagesAndErrors` enters named-file mode only when an operand ends `.go`, `Stat` succeeds, and the result is not a directory (`cmd/go/internal/load/pkg.go:2903–2932`, especially 2911–2918). Local literals that do not enter that route are matched and directory-loaded by `cmd/go/internal/modload/load.go:251–307,526–597` and `cmd/go/internal/search/search.go:276–293`. `runBuild` uses that loader at `cmd/go/internal/work/build.go:459–477`. - **behavior directly implemented or asserted by pinned Go** — official `cmd/go/testdata/script/list_ambiguous_path.txt:1–15,29–36` directly proves that directory `./foo.go` is a package while regular file `./a.go` is a `command-line-arguments` package. Official `cmd/go/testdata/script/mod_symlink_dotgo.txt:1–9,11–17` directly asserts that `dir.go -> dir` is not a source entry; `go/build/build.go:886–900` implements that directory-enumeration rule. - **behavior derived from the pinned implementation** — because the initial `Stat` follows the terminal symlink, a requested `.go` path whose target is a directory takes the directory package route under build. That file-kind rule applies directly to WW's existing local raw-source/directory distinction and needs no module, manifest, registry, cache, network resolution, generalized import syntax, or build expression. #### Ownership and command boundary - **directly measured WW behavior** — before this change, Cstage already stat-routed a valid `visible_test.ww -> pkgdir` build, produced a normal directory graph and executable, and returned status 0 with empty streams. WWstage instead returned status 1, empty stdout, exact `ww: cannot read source\n` stderr, and no artifact. The same split occurred for `visible.ww -> pkgdir` and a real directory named `literal.ww`; a `regular_test.ww` symlink to a regular source retained the aligned 11.51 omission. - **directly measured WW behavior** — the true owner is the requested-kind branch in `selfhost/cmd/ww/main.ww::dobuild`, after its existing `Stat`, prefix exclusion, and non-directory `_test.ww` check and before logical resolution. Cstage and both test fronts already have the required classification and do not change. - **behavior directly implemented or asserted by pinned Go** — `go run` has a deliberately different front door: `cmd/go/internal/run/run.go:95–112` consumes leading `.go` suffix operands as named files without build/test's directory guard, after which `GoFilesPackage` rejects a directory at `cmd/go/internal/load/pkg.go:3274–3281`. - **behavior derived from the pinned implementation** — therefore this slice does not change the shared WW resolver or `ww run`. Multiple operands, recursive patterns, logical names, ordinary directories, regular and non-regular sources, dangling symlinks, raw `ww test`, `test -c`, and `test -S` retain their existing front doors. #### Build, test, package, and import effects - **directly measured WW behavior** — build is the primary axis. The selected request enters the same directory enumeration, graph, action, output, and transaction route as its direct target and the Cstage spelling. A requested `_test.ww` basename is only request metadata; ordinary directory production selection still excludes actual `*_test.ww` entries. - **directly measured WW behavior** — package selection is the mechanism. The requested symlink spelling and physical target remain loader/presentation metadata; downstream canonical local package, graph, action, symbol, artifact, `.wwi`, publication, and persistence identities are unchanged. No fake raw root or spelling-specific generation is created. - **directly measured WW behavior** — imports are exactly the selected directory package's existing dotted imports. The change adds no qualifier, syntax, search order, edge kind, cycle rule, or identity. It makes the established graph reachable instead of failing before directory load. - **directly measured WW behavior** — raw `ww test` was already aligned because both stages independently stat literal test requests. Running tests, `-c` retained binaries, `-S` directory diagnostics, stdout/stderr, and binary bytes matched through the `.ww` symlink before the build fix. Test-process topology and `-run` matching are explicit non-effects. #### Diagnostics, artifacts, and lifecycle - **directly measured WW behavior** — CLI parsing, multi-root/tree delegation, leading-prefix selection, and non-directory `_test.ww` header diagnostics keep their precedence. After directory selection, no-source, package/import/source, output, producer, publication, and collision diagnostics use the existing directory order and requested path presentation. The false raw-source read diagnostic disappears only for this build route. - **directly measured WW behavior** — file output, output-directory publication, exact `/dev/null`, assembly-only `-S`, default output, and persistent `-w` reuse use the existing directory actions and transaction. Cold success creates the same units, `.wwi`, assembly, objects, archives, initializer products, and optional executable as Cstage. Cold source or producer failure commits no partial generation; warm injected compiler failure and signaled-linker failure preserve every prior public and semantic byte and leave no `.new`, install backup, or `.wwtxn.*`. - **directly measured WW behavior** — source/import diagnostics, compiler failure, and a signaled linker preserve the equivalent directory request's prior output and work bytes. The focused concurrent row proves isolated Cstage/WWstage selected requests. The classifier itself is request-local and read-only; unchanged directory machinery continues to own assembler, archiver, ordinary linker and publication failures, shared action locking, driver interruption, process reaping, rollback, and filesystem cleanup. - **directly measured WW behavior** — direct `SIGTERM` of either driver while a selected warm build is blocked in compilation is an inherited lifecycle non-effect, not part of the classifier change. Both stages terminate with shell status 143, reap the complete owned process group, and preserve the prior public output and committed semantic bytes, but the existing directory machinery leaves three request-private `.new` files. That independently verified cleanup gap remains open and this slice does not describe it as fixed. - **directly measured WW behavior** — Cstage and WWstage agree byte-for-byte on status, stdout, stderr, diagnostics, public output, and every semantic artifact for selected success and failure rows. Complete within-stage preservation includes the invoking driver's `.wwtool.ww` provenance snapshot; cross-stage semantic comparison excludes only those intentionally different producer bytes. The focused WW-native observer directly measures direct and symlinked `.ww` directories, the visible `_test.ww` spelling, regular-file omission, directory no-source and source/import precedence, a reachable dotted dependency, default/file/directory/null/assembly outputs, cold and warm reuse/invalidation/rollback, compiler failure and signaled-linker interruption, runtime reachability, selected-route concurrency, cleanup, and the exact test/run command boundaries. No serialized representation changes: build workdir format remains `18`, test workdir format remains `19`, semantic storage format remains `3`, and no cache or result record is added. ### 11.53 Implemented `.ww`-spelled directory run rejection An existing target selected by `ww run` whose exact requested spelling ends `.ww` is a named-source request when ordinary symlink-following `stat` reports a directory. Run rejects that directory before package resolution or private work creation. This is deliberately different from section 11.52's build/test directory route: the command-specific front door, not the shared resolver, owns the distinction. #### Pinned authority and applicability - **behavior directly implemented or asserted by pinned Go** — official Go 1.26.5 commit `c19862e5f8415b4f24b189d065ed739517c548ba` scans leading `.go` operands at `cmd/go/internal/run/run.go:73–112`, rejecting an `_test.go` spelling at 103–109 before passing the named set to `GoFilesPackage`. `cmd/go/internal/load/pkg.go:3244–3289`, especially 3274–3281, follows `Stat` and fatals when a named operand is a directory. Later checking, action construction, linking, and execution at `run.go:141–173` are not reached. - **behavior directly implemented or asserted by pinned Go** — the exact Go status, header-free diagnostic, and terminating newline follow `cmd/go/internal/base/base.go:137–145,175–183`, `cmd/go/main.go:98–100`, and `log/log.go:200–245`. Official `cmd/go/testdata/script/run_hello.txt:1–10`, `run_dirs.txt:1–20`, and `run_set_executable_name.txt:4–17` anchor the named-file run front and its distinction from package-form run. Indirect official directory-kind anchors are `list_ambiguous_path.txt:4–15,29–36`, `mod_get_go_file.txt:47–58`, and `mod_symlink_dotgo.txt:4–9`. No official end-to-end `go run` test asserts this directory diagnostic; the result is implemented directly by the cited source. - **behavior derived from the pinned implementation** — WW's `.ww` named-source spelling and existing directory-package form meet at the same practical boundary. The applicable adaptation uses `WW file` and `*_test.ww` while preserving requested operand bytes. It requires no module, manifest, registry, network lookup, generalized import grammar, cache, database, CAS, or build expression. #### Ownership, selection, and diagnostics - **directly measured WW behavior** — before this change, Cstage followed a direct `.ww` directory or visible `.ww`/`_test.ww` symlink into the ordinary directory graph, invoked compiler, assemblers, linker, and user program, and returned that program's status. WWstage instead entered raw-source loading, returned status 1 with exact `ww: cannot read source\n`, and ran no producer or program. Both removed the private work they had unnecessarily created. - **behavior derived from the pinned implementation** — the true WW owners are only `cmd/ww/main.c::do_run` and `selfhost/cmd/ww/main.ww::dorun`, after their existing option/target parse and requested `stat`, but before `resolve_module`/`resolvemodule` and run scratch creation. Changing the shared resolver would wrongly change the distinct build, test, logical, and dotted-package fronts. - **directly measured WW behavior** — after the run-local classification, both stages return status 1 with empty stdout. A requested spelling ending `_test.ww` emits exactly `ww: cannot run *_test.ww files (OPERAND)\n`; every other selected directory ending `.ww` emits exactly `OPERAND is a directory, should be a WW file\n`. The requested operand is reproduced unchanged. `_test.ww` precedence applies before ordinary directory rejection, including through a symlink. - **directly measured WW behavior** — the rule includes direct and symlinked `.ww` directories and hidden directory spellings `.hidden.ww` and `_hidden.ww`. It also precedes malformed package clauses and missing imports inside the directory because no member is selected or opened. Existing run option errors and target determination retain their earlier precedence. A trailing separator does not end `.ww`; non-`.ww` directories and dotted logical requests retain the established package route. #### Build, test, package, and import effects - **directly measured WW behavior** — package/source selection is the primary axis. The rejected request creates no raw or directory package, canonical identity, declared-name instance, test variant, initializer, graph node, or action. Requested spelling and followed target are diagnostic observations only, never canonical package, action, symbol, artifact, `.wwi`, publication, or persistence identity. - **directly measured WW behavior** — build retains section 11.52's stat-first rule for the same direct and symlink spellings. It still enumerates the directory, discovers its dotted dependencies, constructs ordinary package actions, and applies the established default, explicit, directory, `/dev/null`, `-S`, publication, persistence, invalidation, and rollback policies. Unaffected build controls retain stage-byte-identical public and semantic artifacts. - **directly measured WW behavior** — raw `ww test`, `ww test -c`, and directory `ww test -S` retain their stat-first directory selection and established diagnostics/artifact bytes. Test package variants, generated main, process topology, filtering, capture, result ordering, retention, and result non-caching are unchanged. - **directly measured WW behavior** — imports are not scanned on the selected run rejection and create no qualifier or edge. Dotted and non-`.ww` package controls retain exact canonical import identity, dependency discovery, and runtime behavior. No physical directory becomes canonical identity through this rule. #### Actions, lifecycle, parity, and scope - **directly measured WW behavior** — selected rejection invokes no compiler, assembler, archiver, linker, initializer, runtime, or owned child/process group. A fixture-preoccupied exact `/tmp/ww_run_` plus sentinel remains untouched, proving that the driver does not acquire or mutate its run-scratch path; final cleanup leaves that path absent. It also creates no output, `.sepwork`, unit, `.wwi`, assembly, object, archive, executable, capture, result, transaction, stage, backup, or persistent record. Thus producer/runtime failure, publication, reuse, invalidation, and rollback are inapplicable on this preflight route; all prior caller and committed bytes remain untouched. - **directly measured WW behavior** — classification is request-local, read-only, and isolated under concurrency. An interruption in this preflight owns no child or filesystem resource. The general direct-driver interruption gap from section 11.52 remains open: a different request interrupted after transaction staging can still leave fixed-name `.new` files and poison later persistent reuse. This slice neither reaches nor fixes that machinery. - **directly measured WW behavior** — Cstage and WWstage match exactly on status, stdout, stderr, diagnostic bytes, empty producer traces, artifact absence, exact PID-path non-acquisition and final absence, concurrent isolation, and cleanup for every selected row. Unaffected controls retain diagnostic and public or semantic artifact-byte parity. - **behavior derived from the pinned implementation** — this narrow file-kind slice does not implement the complete suffix-first run front. Regular or missing `_test.ww`, missing or logical `.ww`, multiple named sources, finite FIFOs, and hidden regular sources retain their prior routes and remain separately open where different. Recursive requests, ordinary directory requests, and generalized imports are not changed. The focused WW-native observer covers direct, symlinked, hidden, ordinary, and `_test.ww` directory spellings; malformed-package and missing-import precedence; exact requested diagnostics; empty tool/runtime traces; exact PID-path non-acquisition and final absence; concurrency and cleanup; trailing-separator, non-`.ww`, regular-source, and dotted logical run controls; and unchanged same-spelling build and raw/compile-only/assembly-only test boundaries. No serialized representation changes: build workdir format remains `18`, test workdir format remains `19`, semantic storage format remains `3`, and no cache or result record is added. ### 11.54 Implemented wrong-suffix physical-source exclusion One public operand is a local named source only when its exact requested spelling ends `.ww` and the command's existing file-kind rule admits it. An existing non-directory object with any other suffix does not become source and does not preempt the same operand's ordinary dotted lookup. Thus a physical `foo.bar` is ignored as a source while request `foo.bar` continues to `foo/bar.ww` or `foo/bar/`. An existing directory, including a symlink whose target is a directory, remains a stat-first directory package regardless of suffix. #### Pinned authority and applicability - **behavior directly implemented or asserted by pinned Go** — official Go 1.26.5 commit `c19862e5f8415b4f24b189d065ed739517c548ba` enters named-file mode in `cmd/go/internal/load/pkg.go:2887–2932`, especially 2903–2918, only when a requested spelling ends `.go`, `Stat` succeeds, and the result is not a directory. `GoFilesPackage` independently rejects every non-`.go` member at `pkg.go:3244–3318` before constructing its synthetic package. Build and test call that loader at `cmd/go/internal/work/build.go:459–477` and `cmd/go/internal/test/test.go:684–719`. Run independently consumes only leading `.go` spellings at `cmd/go/internal/run/run.go:73–145`, especially 96–123. - **behavior directly implemented or asserted by pinned Go** — official `cmd/go/testdata/script/list_test_non_go_files.txt:1–13` directly tests a mixed named-file list: after a `.go` member selects named-file mode, `GoFilesPackage` rejects the non-`.go` member. Official `run_hello.txt:1–10` and `run_set_executable_name.txt:4–17` anchor ordinary named-file and package run fronts. None directly tests one existing wrong-suffix object colliding with a package request, and the official tree contains no such singular build/run/test script. - **behavior derived from the pinned implementation** — the singular collision result follows from the pinned suffix-before-`Stat` build/test gate and run's suffix-only scan. WW's honest local adaptation applies the same positive spelling decision to `.ww` named sources before its existing dotted search. It requires no module, manifest, registry, network lookup, generalized import syntax, cache, database, CAS, lock, or source expression. #### Ownership, selection, and identity - **directly measured WW behavior** — before this change, both stages adopted an existing physical `foo.bar` as a raw source. Build and run therefore used its package, imports, main, and runtime status instead of `foo/bar.ww`; raw, compile-only, and assembly-only test used its test descriptors and retained its semantic/public bytes. Removing only `foo.bar` selected the logical provider and changed all of those observations. - **behavior derived from the pinned implementation** — the true shared owners are `cmd/ww/main.c::resolve_module` and `selfhost/cmd/ww/main.ww::resolvemodule`. Their direct non-directory adoption now requires the exact `.ww` requested spelling. The mirrored spelling predicate also owns build/run requested-literal bookkeeping and raw test's second-positional classifier plus main stat/resolution branch. These command fronts distinguish direct directory, eligible direct source, and logical resolution without moving the rule into the compiler, enumerator, graph, coordinator, producer, or runtime. - **directly measured WW behavior** — a resolved logical single-file provider retains the established command-line-file root family `__root.*`; selection by a dotted request does not invent a dotted storage identity. A resolved logical directory retains its dotted package/import/action family such as `foo.bar.*`. The ignored physical pathname, object kind, containing directory, bytes, mode, and timestamp create no package member, qualifier, graph node or edge, action, symbol, `.wwi`, initializer, artifact, publication destination, or persistence key. The logical requested spelling remains canonical request identity where the existing directory route uses it. - **directly measured WW behavior** — requested suffix, not a symlink target's basename, owns the positive gate. A wrong-suffix symlink to a regular or non-directory special object is ignored as source; a wrong-suffix symlink to a directory follows ordinary directory routing. A visible `.ww` symlink to a regular source remains eligible. Each stage retains its prior visible `.ww` special-file kind handling; this slice does not make FIFO/device loading a shared new contract. #### Build, test, package, and import effects - **directly measured WW behavior** — with a logical provider, build produces the same source set, import closure, initializer graph, producer calls, runtime result, public output, and persistent artifacts whether the wrong-suffix object is absent or present. Run executes that same provider. Raw/running test, the historical second-positional test-name filter, `test -c`, and `test -S` select the same logical test package, descriptors, support closure, binary, and assembly. Cstage and WWstage outputs and every comparable semantic artifact are byte-identical. - **directly measured WW behavior** — the ignored object's package clause, imports, malformed bytes, checker failures, abort/nonzero behavior, and timestamps are not source input and cannot displace logical-provider diagnostics. Package membership and import edges are exactly those of the provider. A logical directory retains its dotted identity and a logical file retains `__root`; physical collision state supplies neither. - **directly measured WW behavior** — when no logical provider exists, a collision matches the absent-physical control. An ordinary build or run emits its existing `cannot find module` diagnostic; raw test emits its existing `cannot find` diagnostic plus `FAIL` only when running; `-c` and `-S` omit that marker. A second positional deliberately retains the historic package-coordinator route and its exact canonicalization or usage result, rather than being silently redefined as a direct cannot-find path. Existing flag, output, tree, package-option, hidden-source, named `_test.ww`, and `.ww` run-directory precedence remains unchanged. - **behavior derived from the pinned implementation** — all four permanent axes meet at this one source-eligibility decision. Build no longer constructs or publishes the wrong action; test no longer constructs or runs the wrong test package; package membership is not stolen by an ineligible physical filename; and import binding/initialization comes only from the logical provider. No axis receives a compatibility bypass or new identity model. #### Lifecycle, parity, formats, and scope - **directly measured WW behavior** — changing the collision among absent and stat-successful non-directory states does not invalidate semantic actions or alter semantic bytes or producer inputs. An unchanged warm command still performs the established final link and success publication, producing the same public bytes while its inode and mtime may change. Replacing the collision with a directory, or retargeting a symlink to a directory, leaves this case and follows ordinary stat-first directory behavior; no new atomic snapshot promise is made for a concurrent kind change. - **directly measured WW behavior** — logical producer failure preserves the prior public and semantic generation. A retained running-test runtime failure occurs after the complete logical build generation commits: deferred public installation is skipped, so prior retained public bytes survive while the newly built semantic generation remains committed and reusable. Restoring the prior source requires a later successful rebuild and commit, not rollback of the runtime-failing generation. Normal completion and controlled failures remove request-owned scratch and transaction fragments. The spelling gate is request-local and allocates no state before logical action or coordinator start; concurrent requests use separate destinations and the existing logical-action synchronization. - **directly measured WW behavior** — external signal interruption after an action starts is unchanged. In particular, the verified direct-driver fixed `.new` leakage and later persistent-request poisoning remain open. This source classifier neither prevents nor recovers that residue and makes no signal-cleanup claim. - **behavior derived from the pinned implementation** — the rule does not complete the remaining suffix-first run front, multiple named sources, finite `.ww` FIFO capture, shared test-process state/failure topology, Go-compatible `-run` regular expressions, or `package documentation` suppression. Existing `.ww` directory slices, hidden-source exclusion, named `_test.ww` build omission, recursive/multiple-root coordination, package syntax, and import syntax remain intact. Build workdir format remains `18`, test workdir format remains `19`, and semantic storage format remains `3`. No schema, action descriptor, cache/result record, manifest, transaction protocol, or lock changes. ## 12. Candidate architectures and hard-gate decision Five candidates were developed as coherent systems, not as feature bins. ### 12.1 Candidate A: Go-like integrated language command One `ww` command would infer directory packages/imports, compile/cache/test them, and add a small module/lock layer. Native inputs would remain compiler flags or toolchain conventions. This preserves the strongest part of Go: explicit imports, fast direct export data, and a short ordinary command ([Go command design](https://go.dev/doc/articles/go_command)). A WW-specific lock and no-network build could improve on modern Go module behavior. It still fails as an end-to-end native design. A source-only graph cannot name host generators, C header trees, archive order, linker scripts, CRT, SDK, or sysroot. Ambient compiler-driver and `pkg-config` behavior would remain outside the key, and the build/host/target triad would be incomplete. Adding typed native actions, complete toolchains, and content records turns it into Candidate E. ### 12.2 Candidate B: Hare/Odin-style local source plus an outer build tool WW would use search roots and directory modules, with source vendored or supplied by an OS package manager; Make-like orchestration would own native work. This is small locally and avoids a language-owned network resolver. Hare 0.26.0 (released 2026-02-13) is a useful reference: directory modules, direct textual export data, `HAREPATH`, explicit system-library flags, and cross-architecture tooling are documented in its official manuals ([modules](https://harelang.org/documentation/usage/modules.html), [project structure](https://harelang.org/documentation/usage/project-structure.html), [system libraries](https://harelang.org/documentation/usage/system-libraries.html), [cross compilation](https://harelang.org/documentation/usage/cross.html)). Odin's named collections are a related local-source convention ([Odin overview](https://odin-lang.org/docs/overview/)). As a complete WW system it fails: ordered search roots are selection policy without locked source identity; ordinary outer recipes expose ambient tools, environment, and mtimes; language and native graphs/caches cannot jointly explain invalidation; and cross sysroots/ABI providers remain project conventions. Making the outer tool hermetic and content-addressed yields Candidate C, not this model. ### 12.3 Candidate C: two-layer Plan 9-style builder and orchestrator A strict package builder would compile an import graph. A separate small declarative DAG tool would own generators, C/assembly, images, archives, and links. With content records, pinned tools, sandboxing, and an exact handoff this can pass every hard gate. It reflects `mk`'s valuable complete-graph/parallel-tool shape without copying its mtime and ambient-environment assumptions. It loses after the gates because the boundary creates two graph protocols, two selection UIs, two explanation namespaces, and either duplicate scheduling/cache logic or a coarse “build all packages” action. Ordinary native projects must know when to invoke each layer. If both front ends lower into one shared scheduler and cache, and `ww` owns the ordinary invocation, the result is the smaller Candidate E. Keeping the second production tool after that offers no remaining orthogonal concept. ### 12.4 Candidate D: Zig/Cargo-like programmable integrated project A manifest would define artifacts and dependencies while a host-executed program constructs a flexible native graph. This handles more native cases than a language-only command. Zig 0.16.0, pinned here to its 2026-04-13 release metadata, provides explicit target/native concepts, hashed package sources, local dependency overrides, and generated-file graph edges ([download metadata](https://ziglang.org/download/index.json), [0.16.0 reference](https://ziglang.org/documentation/0.16.0/), [build system](https://ziglang.org/learn/build-system/)). Cargo 1.97.1, shipped with Rust 1.97.1 on 2026-07-16, provides exact package IDs, workspaces, lock checksums, resolver rules, and native `links` collision handling ([Cargo reference](https://doc.rust-lang.org/1.97.1/cargo/reference/), [resolver](https://doc.rust-lang.org/1.97.1/cargo/reference/resolver.html)). Zig's build program and Cargo's `build.rs` execute to decide or report build behavior; Cargo explicitly documents build-script inputs/outputs and its fingerprint cache ([build scripts](https://doc.rust-lang.org/1.97.1/cargo/reference/build-scripts.html), [build cache](https://doc.rust-lang.org/1.97.1/cargo/reference/build-cache.html)). Those reference systems as shipped do not meet WW's complete native/toolchain hard gates. The strongest coherent D is not left as a straw man: it content-identifies the graph program and host compiler/runtime, declares its whole readable source/tool closure, runs it in the denied-by-default sandbox with no network, and requires it to emit a closed typed graph before artifact execution. That hardened model can pass every gate. It still loses afterward: WW must permanently ship/secure/ bootstrap an evaluator API and host build-program toolchain, users debug both program execution and its emitted graph, dependencies expose framework APIs, and routine exceptions accumulate as library features. Finite records buy the same WW requirements with less user and implementation machinery. ### 12.5 Candidate E: hermetic integrated action build — selected Candidate E retains the Go-like ordinary UX and import-derived language graph, then adds only the native/action facts that imports cannot express. Both lower to one typed graph and content cache. It borrows declared tools/inputs and action results from Bazel's hermetic/remote-execution model, and transparent content-derived build records from Nix derivations, without adopting either framework, evaluator, daemon topology, or user interface ([Bazel hermeticity](https://bazel.build/versions/9.2.0/basics/hermeticity), [Bazel remote caching](https://bazel.build/remote/caching), [remote execution protocol](https://github.com/bazelbuild/remote-apis/blob/master/build/bazel/remote/execution/v2/remote_execution.proto), [Nix derivations](https://nix.dev/manual/nix/2.35/store/derivation/)). It passes every hard gate and is selected. Its concepts are exactly package, module/source selection, product/action, toolchain/target, artifact/digest, and native provider/link plan. There is one graph, one scheduler, one cache key, one explanation path, and one ordinary command. ### 12.6 Hard-gate matrix Legend: **pass** means the strongest coherent form has a credible end-to-end invariant; **fail** means it does not. D denotes the hardened evaluator above, not unmodified Zig/Cargo behavior. | Hard gate | A: Go-like | B: local + outer | C: two layer | D: programmable | E: action build | |---|---|---|---|---|---| | complete inspectable dependency DAG | fail for native work | fail across tools | pass | pass after sandboxed evaluation | **pass** | | loud cycles/identity collisions | pass for packages; native incomplete | search shadowing fails identity | pass | pass | **pass** | | frozen offline source closure | pass with proposed lock | vendoring can pass | pass | pass | **pass** | | correct cache invalidation | fail for native/tool defaults | fail across mtime/outer recipes | pass | pass | **pass** | | compiler/linker/runtime/toolchain identity | requires the E native layer | fail | pass | pass | **pass** | | explicit B/H/T | fail | fail | pass | pass | **pass** | | correct native dependency/link modeling | fail | fail | pass | pass | **pass** | | deterministic package selection | pass | fail under search roots | pass | pass with lock | **pass** | | reproducible artifacts/boundary | fail for native closure | fail | pass | pass with evaluator certification | **pass** | | bounded bootstrap | pass with a seed | pass with enumerated seed/tools | pass | pass, larger evaluator TCB | **pass** | | explain cache miss/rebuild | fail | fail | pass across two namespaces | pass across evaluation + graph | **pass** | | one simple ordinary path | pass | two commands/configurations | two production layers | pass by convention | **pass** | | no build/test network or mutation | pass if changed from Go defaults | outer recipes cannot guarantee | pass | pass | **pass** | C, hardened D, and E survive the gates. E wins the requested post-gate comparison: | Criterion | C: two layer | D: hardened evaluator | E: selected | |---|---|---|---| | conceptual simplicity | two graph/handoff models | evaluator language/API plus emitted graph | one graph protocol; two finite descriptions | | daily usability | user chooses builder/orchestrator | ordinary defaults can hide evaluator, exceptions cannot | `ww build/test/run` always | | clean speed | parallel orchestration can match | evaluation overhead, then parallel graph | direct complete template plus parallel actions | | incremental speed | cross-tool handoff may be coarse | evaluator must rerun/cache its own dependencies | direct exports, lazy content keys, cached link | | rebuild blast radius | good only with API digests across handoff | can be good after evaluation | public-output digest propagation is intrinsic | | cross-compilation | orchestrator can model it | rich API can model it | roles are built into every typed record | | FFI/native honesty | outer layer owns it separately | API can express it | same provider/link records as package objects | | implementation maintenance | two adapters/engines or coarse boundary | evaluator, SDK compatibility, sandbox, graph engine | one scheduler/store/adapter set | | supply-chain security | two policy surfaces | dependency host code remains an evaluator input | one lock/source/action trust model | | ecosystem scalability | two tool ecosystems | framework/API accumulation pressure | closed schemas version only for demonstrated facts | | debugging/observability | two explanation namespaces | debug program, evaluator cache, then graph | one causal graph/record diff | | bootstrap longevity | small outer interpreter possible | compiler/runtime/evaluator enter seed chain | fixed seed plan; no production evaluator | ### 12.7 Why each subsystem is in or out of the core Package parsing/resolution and export data belong in the core because only the compiler can state the true language graph and public ABI. Module selection and lock verification belong beside it because an import identity must resolve to one deterministic source before compilation. The typed action engine, target descriptors, native providers, and toolchain closure belong in the core because they share invalidation and link correctness with package objects. Test/doc/ install are thin product selections/materializations over that same graph. Network transport remains a separate operation, though exposed by `ww`, because fetching is not building. Credential policy, OS package installation, registry hosting, signing authority, remote execution, deployment, and general release automation stay outside. The finite `generate` action is the boundary: it lets outer domain tools transform declared artifacts without turning WW into their framework. ## 13. Migration plan Migration cost does not affect the decision. It is nevertheless material: the current directly implicated scaffolding is at least 7,969 lines across the Makefile, two drivers, two interface writers, package coordinator, and test wrapper, plus 4,728 lines in the focused separate-build/package/byte-identity/ driver tests counted for this audit. Compiler export/import logic, new native adapters, and bootstrap work add new scope not represented by those deletion counts. The planning estimate is **15–22 engineer-months** for the first production Linux/amd64 toolchain, including tests, migration, and deletion, plus **1–2 engineer-months per materially different additional official target/sysroot**. This is an estimate for staffing and sequencing, not a reason to retain a weaker architecture. Every phase below ends in a bisect-clean commit. Experimental components are not installed as a second user-facing build path. Until the point of no return, the old command remains the only production path; after it, the new command is the only path. ### Phase 0 — conformance corpus and protocol freeze - Land the compact checked-in `protocol/schema/` modules for WWAR framing, record/enum/union/default/kind assignments, wrappers, and finite digest byte formulas. Freeze the exact schema-file digests. Preserve representation-only preimage records without embedding the algorithms that construct them. - Generate data-only codec tables deterministically. Keep one schema-aware reference codec and a second independent oracle limited to raw WWAR framing, hashing, and record identity; neither may implement future compiler or build behavior. - Gate: strict duplicate-key UTF-8/NFC schema loading, byte-identical generation in separate fresh directories, compact valid/invalid vectors, all assignment coverage, stable malformed-length precedence, domain separation, action-key vectors, and record-kind substitution rejection. No production behavior changes beyond adding this conformance gate. - Package/API, graph/cache, native B/H/T, and bootstrap measurements remain useful fixtures, but become tests in Phases 1, 2, 4, and 6 respectively. They are not Phase 0 semantic answer tables. ### Phase 1 — compiler export and package protocol - Implement deterministic `.wwe`/`.wwlm` writing and direct-interface reading in Cstage and self-hosted compiler paths behind test-only entry points. - Add package identity/alias syntax, strict directory enumeration, compiler import extraction, target suffix selection, cycle/collision/internal checks, and protocol compatibility diagnostics. - Construct and test the deep public type closure and public type/ABI digest preimages in compiler code with existing standard-library graphs. Reject `.wwi` input in the experimental path; do not translate it. - Gate: Cstage/WWstage emit byte-identical vectors, importers open only direct export files, and API propagation stops on unchanged middle exports. ### Phase 2 — one action engine and local CAS - Integrate the frozen WWAR codec into production code and implement typed pure action-record/key functions, the action graph, lazy keys, scheduler, atomic CAS/results, project index, corruption quarantine, graph JSON, environment and sandbox policy, deterministic failure behavior, and causal explanation. - Add deterministic package/archive/link adapters using the existing compiler, assembler, and linker as explicitly hashed tools. This is a temporary adapter, not a compatibility promise. - Keep the engine under an internal test binary; the installed `ww` still follows the old production path. - Gate: all action-input mutation and failure-injection tests pass; identical warm builds execute no compiler, assembler, archiver, or linker. ### Phase 3 — module, lock, source, and workspace layer - Implement the manifest, lock, work, and vendor text parsers as ordinary typed parser code, then implement the closed grammar, monotonic selector, canonical lock, HTTPS source-index/archive protocol, immutable source store, signatures, explicit add/update/lock/fetch, overlays, vendor index, and canonical source-tree construction. The schema fixes only the resulting record bytes and source-tree digest formula. - Build/test/doc/install remain network-denied from their first experimental use. - Gate: frozen offline builds work from project source + complete locked source closure + lock + installed named toolchain; collision/downgrade/hash/ path-normalization attacks fail loudly. ### Phase 4 — native, target, and external toolchain closure - Implement full target descriptors, B/H/T lowering, C/assembly/native-provider records, recursive provider selection/expansion, generated actions/sandbox, object sidecars, exact link-plan construction, sysroot, libc/CRT/loader/SDK/runtime, shared-library installation, and freestanding products. - Package supported assembler/linker/archive/C tools as immutable external closures. Implement an external-assembler-compatible textual emission backend, then have the pinned assembler produce `package.o` inside `ww.package`; port all WW/Plan-9-dialect runtime and user assembly to a declared supported external dialect, and pass object/link parity. An argv adapter alone cannot consume current `w6a` syntax. Stop relying on WW-owned `w6a`/`w6l` before the experimental gate passes. - Gate: native conflict, archive group/order, linker-script include, host leak, freestanding, shared loader, and at least one real cross-target suite pass. ### Phase 5 — repository and consumer conversion rehearsal - Define the final identity/layout conversion in a one-shot checker/rewriter under `tools/migrate-build/`: folded files become directory packages; aliases, manifests, native providers, products, generated inputs, and locks are emitted. It is not an import resolver or runtime compatibility layer. - Until cutover, CI applies that tool to a fresh ignored shadow tree. Tracked production source stays in old syntax, so the old command remains its only production path; the shadow is regenerated, never a second maintained source tree or shipped interface. - Dogfood the internal engine on the converted shadow of the standard library, compiler tools, tests, examples, install layout, CI/package inputs, and sample downstream consumers. Compare semantics, diagnostics, performance, artifacts where protocols permit, and complete graph explanations. - Gate: the regenerated full shadow, distribution/frozen-offline build, self-contained installed toolchain outside the build tree, downstream samples, and bootstrap inputs pass without an old-format edge. ### Phase 6 — new bootstrap and reproducible release - Implement/gate the portable C recovery backend and snapshot generator, then generate/check in `bootstrap/ww0.c` and the fixed plan. Produce stages 1/2/3/4, rebuild stages with the executable engine, compare the actual bytes of every declared output directly, and produce fixed-point and diverse-seed-compilation reports, signed toolchain bundles, and recovery documentation on a clean machine with no WW compiler. - Gate: stage 2 equals stage 3 and stage 3 equals stage 4 by explicit byte-for-byte comparison, including raw action/result records, in two roots/concurrency levels; project plus complete locked source closure and published named tool closure reproduce every release artifact. ### Phase 7 — point of no return and deletion In one atomic, bisect-clean cutover commit: 1. install the new engine as `ww` and make it the sole build/test/bootstrap path; 2. switch repository imports, manifests, locks, toolchains, CI, installation, and release jobs to their final forms; 3. delete both old drivers, both `.wwi` writers, driver-side `.wwi` concatenation, composed-unit/module-wrapper logic, generic C/self-hosted lexer/parser/checker/ symbol/codegen support for module directives, `-w`, old import search/file folding, separate test coordinator, duplicated production Make dependency graph, current Cstage bootstrap, and retired owned assembler/linker path; and 4. delete the migration rewriter after all supported consumers have used its released standalone copy; keep only a format-error guide. The commit does not accept old `.wwi`, dotted/file imports, `-I`, `-w`, raw library searches, or old work directories. No alias, warning period inside the compiler, environment switch, or fallback subprocess retains a dual system. ### Phase 8 — consolidation - Remove temporary parity fixtures that test deleted artifact bytes while retaining semantic, action-key, reproducibility, and bootstrap regression tests. - Publish migration statistics and archive the old documentation as historical release material outside the live manual. - Gate: repository search and executable tracing show one graph constructor, one package resolver, one cache, one test route, and one bootstrap route. ## 14. Validation plan and release gates ### 14.1 Unit and format tests - Phase 0 has golden and adversarial vectors only for WWAR representation, source-tree digest bytes, action-key/record identity formulas, typed record assignments, wrappers, and canonical schema JSON. - Phase 0 tests UTF-8/NFC, duplicate schema keys, unknown wire type/schema field, oversized declarations, truncation, exact-length mismatch, union shape, and record-kind substitution. Case-fold collision, traversal, symlink/device, cache collision/corruption, and semantic record tests land with their owning executable phases. - Phases 1–4 add behavior tests for CAS tree/result objects, `.wwe`, `.wwlm`, manifest/lock/work/vendor parsing, and target/toolchain/native processing; these are not encoded as Phase 0 vector outcomes. - Resolver vectors for minimum selection, incompatible-major identities, workspace identity preservation, source origin independence, vendor matching, internal packages, aliases, nested module/root-versus-parent-subpackage identity collisions (including `/vN`), cycles, and target source specificity. ### 14.2 Package/interface tests - One- and multi-file directory membership, file-scoped import use, same/external tests, test-only packages, examples/docs, and generated fragments with import/ package rejection. - Direct dependency interface-open counts equal package-graph indegree, never transitive closure size. - Private dependency edits preserve importer keys; exported but unused additions rebuild direct importers; unchanged middle `.wwe` stops propagation; layout, calling-convention, runtime ABI, compiler, target, and profile changes rebuild the exact affected cone. - Parameter renames, comments, private declaration ordering, and absolute source paths do not change `.wwe`; semantic/ABI changes do. ### 14.3 Native and link tests - C scalar/aggregate/variadic/callback/TLS/unwind ABI probes against an independently compiled C harness for every official target. - Binding generation changes on header tree, macro map, preprocessor, tool, C ABI, and target; undeclared include access is denied. - Assembly dialect/CPU mismatch, wrong-format objects, PIC/shared rules, archive extraction order, repeated libraries, groups, whole archive, weak/strong symbols, version scripts, linker-script includes, and deterministic archives. - Exactly-one libc/runtime/provider enforcement; identical coalescing; duplicate native ABI/symbol conflict; shared SONAME/loader/runtime installation closure; freestanding entry/script with proof that no libc/CRT/loader appears. ### 14.4 Cross and sandbox tests - Matrix with `B != H`, compiler product `H != T`, and all three distinct where infrastructure permits. A B generator emits an H input; an H binary is never executed during build; T objects never enter the H link. - Poison host `PATH`, includes, libraries, SDK, locale, time, home, current directory, and environment. Every attempted undeclared read/write/network/ process/tool access fails with its action identity. - Cross tests build without a runner, run only with an exact declared runner, and fail under `--require-run` when none exists. ### 14.5 Cache and failure injection - Change each field in section 6.2 individually and require a key change; change each expressly non-semantic observation and require no key change. - Bit-flip blobs, trees, results, action mappings, tools, export data, objects, and partial files at every publication boundary. Require quarantine/rebuild, never acceptance or broad deletion. - Concurrent identical publishers, killed compiler/linker, disk full, rename failure, read-only output, interrupted materialization, stale project index, malicious remote mapping, bad cache signature, and remote outage. - Clean, local-hit, explicit remote-import, and no-cache builds must yield the same result digests. Test executions still run. ### 14.6 Reproducibility and bootstrap - Compare every artifact/action record across two absolute checkouts, source/ cache/output roots, usernames, locales, time zones, umasks, concurrency levels, filesystem enumeration orders, and cold/warm caches. - Verify debug/release, static/shared, hosted/freestanding, generated/native, and signed/unsigned products. Impure profiles must state exactly why they are outside the byte promise and must never enter shared cache. - Build `ww0` with each supported host C toolchain, reach stages 2/3/4, run the semantic then raw-record fixed point and diverse seed compilation, corrupt each stage input, and recover on a host with no WW installation. ### 14.7 Performance and migration gates On the audit's fixed eight-CPU reference host, the first release MUST: - run package compilation in parallel and complete the full clean toolchain build no slower than the measured 15.515 s `make -j8` baseline; - perform a warm 15-package build with no compiler, assembler, archiver, or linker process and no slower than the measured 0.053 s driver baseline; - read only direct exports and avoid composed-unit duplication; - store one CAS copy of duplicate tool/package content across all products; - produce fully path-independent official artifacts, including host-side tools; and - provide a typed explanation for every deliberately induced rebuild. Before cutover, every tracked current package/test/install/bootstrap consumer has an assigned new identity and a passing converted test. The cutover gate includes a repository-wide search for old forms and executable traces proving no old driver, interface, workdir, library search, or test-coordinator path executes. ## 15. Evidence appendix ### 15.1 Research method and version pins Research used official documentation, standards/manuals, release metadata, and current upstream source—not comparison articles or community summaries. The evolving-system snapshot was taken 2026-08-09: | System | Pinned snapshot used | |---|---| | Plan 9 | live official `9p.io` Volume 2 documents, accessed 2026-08-09; pages are not versioned/dated editions | | Go | online docs accessed 2026-08-09; Go 1.26.5 `go1.26.5` source tag | | Hare | online docs accessed 2026-08-09; Hare 0.26.0 source, released 2026-02-13 | | Odin | online docs accessed 2026-08-09; `dev-2026-07a`, commit `819fdc7a80667498b8b365999f1475a66c358640` | | Zig | Zig 0.16.0, official metadata release date 2026-04-13; source archive SHA-256 `43186959edc87d5c7a1be7b7d2a25efffd22ce5807c7af99067f86f99641bfdf` | | Rust/Cargo | Rust/Cargo 1.97.1, released 2026-07-16; Cargo `0.98.0` commit `c980f4866141969fab6254a680546a277789d6f0` | | Bazel | Bazel 9.2.0 documentation/source | | Nix | Nix 2.35.2 manual/source | Zig's separate bootstrap-source archive inspected for this decision had SHA-256 `2a8266a4205772ef40838c8cbdf14875855a515ff3adf89b49c2d2ae93613d10`. These pins matter because programmable-build and package behavior changes between releases; this document does not generalize an old Zig/Cargo observation to an unidentified current version. ### 15.2 Primary-source findings **Pike, Plan 9, and early Go.** Pike's sources support explicit computable imports, cycle rejection, direct compiled export information, fast compilation, and orthogonal concepts. The collective Plan 9 papers add system-wide placement of complexity and transparent encodings. Plan 9's namespace papers demonstrate contextual filesystem composition; this document infers that contextual location must not serve as WW's versioned distribution identity. `mk` shows complete graph scheduling while still relying on timestamps, recipes, and environment. The architecture borrows the former principles and replaces the latter ambient assumptions. - [The Go Programming Language, 2009](https://go.dev/talks/2009/go_talk-20091030.pdf) - [Go at Google: Language Design in the Service of Software Engineering, 2012](https://go.dev/talks/2012/splash.article) - [Simplicity is Complicated, 2015](https://go.dev/talks/2015/simplicity-is-complicated.slide) - [Go in Go, 2015](https://go.dev/talks/2015/gogo.slide) - [Plan 9 overview](https://9p.io/sys/doc/9.html) - [The Use of Name Spaces in Plan 9](https://9p.io/sys/doc/names.html) - [Maintaining Files on Plan 9 with Mk](https://9p.io/sys/doc/mk.html) - [Plan 9 Mkfiles](https://9p.io/sys/doc/mkfiles.html) - [Plan 9 compiler suite](https://9p.io/sys/doc/comp.html) **Later Go.** The original Go command demonstrates source-derived package DAGs, directory conventions, and compiler-owned dependency work. The modern module reference documents module identity, Minimal Version Selection, major-version paths, checksums, and commands that may resolve/download modules. Current command and source-install documents also separate build cache/toolchain/bootstrap behavior. These are evidence, not automatic WW defaults; in particular WW uses an exact lock and forbids implicit build-time acquisition. - [About the Go command](https://go.dev/doc/articles/go_command) - [Go module reference](https://go.dev/ref/mod) - [`go` command reference](https://go.dev/cmd/go/) - [Go toolchain selection](https://go.dev/doc/toolchain) - [Installing Go from source](https://go.dev/doc/install/source) - [Perfectly Reproducible, Verified Go Toolchains](https://go.dev/blog/rebuild) - [Go's supply-chain security](https://go.dev/blog/supply-chain) - [`go1.26.5` source](https://go.googlesource.com/go/+/refs/tags/go1.26.5/) **Local-source systems.** Hare demonstrates how far a disciplined directory module/search-root system can go with little package machinery; its documented system-library and cross interfaces also expose why raw host paths and tool defaults are insufficient for WW's hard gates. Odin's collections reinforce the local namespace option but do not add a locked whole native closure. - [Hare modules](https://harelang.org/documentation/usage/modules.html) - [Hare project structure](https://harelang.org/documentation/usage/project-structure.html) - [Hare system libraries](https://harelang.org/documentation/usage/system-libraries.html) - [Hare cross compilation](https://harelang.org/documentation/usage/cross.html) - [Hare 0.26.0 source](https://git.sr.ht/~sircmpwn/hare/tree/0.26.0) - [Odin overview](https://odin-lang.org/docs/overview/) - [Odin pinned source](https://github.com/odin-lang/Odin/tree/819fdc7a80667498b8b365999f1475a66c358640) **Integrated project systems.** Zig supplies useful target/native vocabulary, source hashes, local aliases, declared generated-file edges, and cross-building. Cargo supplies package IDs, exact lock checksums, workspace behavior, resolver documentation, and a native `links` uniqueness rule. Their programmable build program/script model is deliberately rejected; a dependency host program is a larger and less inspectable abstraction than WW's finite action record. - [Zig build system](https://ziglang.org/learn/build-system/) - [Zig overview](https://ziglang.org/learn/overview/) - [Zig 0.16.0 language reference](https://ziglang.org/documentation/0.16.0/) - [Zig release metadata](https://ziglang.org/download/index.json) - [Zig 0.16.0 source](https://github.com/ziglang/zig/tree/0.16.0) - [Cargo 1.97.1 reference](https://doc.rust-lang.org/1.97.1/cargo/reference/) - [Cargo current reference entry](https://doc.rust-lang.org/cargo/reference/) - [Cargo 1.97.1 resolver](https://doc.rust-lang.org/1.97.1/cargo/reference/resolver.html) - [Cargo current resolver entry](https://doc.rust-lang.org/cargo/reference/resolver.html) - [Cargo 1.97.1 build scripts](https://doc.rust-lang.org/1.97.1/cargo/reference/build-scripts.html) - [Cargo current build-script entry](https://doc.rust-lang.org/cargo/reference/build-scripts.html) - [Cargo 1.97.1 build cache](https://doc.rust-lang.org/1.97.1/cargo/reference/build-cache.html) - [Cargo current build-cache entry](https://doc.rust-lang.org/cargo/reference/build-cache.html) - [Cargo pinned source](https://github.com/rust-lang/cargo/tree/c980f4866141969fab6254a680546a277789d6f0) **Hermetic invariants.** Bazel defines useful distinctions between declared actions, execution platforms, action results, and content-addressed remote data. Nix derivations demonstrate an inspectable build record whose output depends on declared inputs. WW borrows those invariants only. It rejects Bazel's general rule/ecosystem machinery and Nix's evaluator/store-as-package-manager as excess for one language toolchain. - [Bazel current hermeticity entry](https://bazel.build/concepts/hermeticity) - [Bazel 9.2.0 hermeticity](https://bazel.build/versions/9.2.0/basics/hermeticity) - [Bazel remote caching](https://bazel.build/remote/caching) - [Remote Execution API](https://github.com/bazelbuild/remote-apis/blob/master/build/bazel/remote/execution/v2/remote_execution.proto) - [Bazel 9.2.0 source](https://github.com/bazelbuild/bazel/tree/9.2.0) - [Nix current derivation entry](https://nix.dev/manual/nix/latest/store/derivation/) - [Nix 2.35 derivations](https://nix.dev/manual/nix/2.35/store/derivation/) - [Nix build process](https://nix.dev/manual/nix/2.35/store/building.html) - [Nix 2.35.2 source](https://github.com/NixOS/nix/tree/2.35.2) **Native and reproducible toolchains.** LLVM and Clang define data-layout and cross/toolchain choices that must be explicit for ABI-correct code. GNU manuals document build/host/target vocabulary and semantic linker/archive/script behavior. The reproducible-builds definition supplies the correct boundary: same source, environment, instructions, and dependencies—not merely “same compiler source.” - [LLVM language-reference data layout](https://llvm.org/docs/LangRef.html#data-layout) - [Clang cross compilation](https://clang.llvm.org/docs/CrossCompilation.html) - [Clang toolchain](https://clang.llvm.org/docs/Toolchain.html) - [Autoconf target triplets](https://www.gnu.org/software/autoconf/manual/autoconf-2.71/html_node/Specifying-Target-Triplets.html) - [GCC language standards/runtime implications](https://gcc.gnu.org/onlinedocs/gcc/Standards.html) - [GCC link options](https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html) - [GNU linker](https://sourceware.org/binutils/docs/ld.html) and [linker scripts](https://sourceware.org/binutils/docs/ld/Scripts.html) - [Reproducible Builds definition](https://reproducible-builds.org/docs/definition/) ### 15.3 Repository and empirical evidence record The source audit covered the Makefile; C and self-hosted drivers; compiler entry and both interface writers; package/test coordinator; language and test specs; bootstrap documents/recipes; and package, separate-compilation, incremental, byte-identity, and bootstrap tests. The audit found documentation drift as well as code defects: the root instructions count five unit suites while Make lists six, and the test-system document describes three pinned data byte divergences while the current Make divergence list is empty. Neither drift item influences the architecture, but both require cleanup during migration. Raw commands, timings, traces, hashes, fixture logs, environment capture, and interpretation for section 11.4 are retained in the session checkpoint under `empirical/RESULTS.md` and `empirical/raw/`. The experiments were deliberately small and answered only material uncertainties: actual process scheduling, direct versus transitive interface consumption, private/public/link-only blast radius, nonzero corruption, path identity, Cstage/WWstage symmetry, duplicate storage, and hidden-host execution. No toy result is treated as proof that the new architecture is complete; sections 13–14 turn each inference into a gate. ### 15.4 Assumptions - Breaking import syntax, package layout, compiler flags, cache/workdir format, bootstrap artifacts, and consumer builds is authorized. - WW can add explicit C ABI/representation annotations and change its compiler export protocol without preserving `.wwi` compatibility. - Official releases can distribute or name legally usable immutable tool, sysroot, runtime, and SDK closures for each supported target. - SHA-256 is the version-1 content primitive; every format is domain-separated and versioned so a future digest transition can be explicit. - A first release may support fewer frozen targets than impure development targets; it may not call an impure target “hermetic.” - Byte reproducibility covers build artifacts, not identical behavior of an external kernel, firmware, network service, or hardware. ### 15.5 Remaining risks and bounded experiments These experiments are implementation gates inside the selected architecture; they do not reopen its package identity, no-script, one-graph, lock/network, direct-export, content-key, native-provider, or stage-zero choices. 1. **Deep `.wwe` closure.** Prototype the real standard-library type graph and prove that one direct export file contains every transitive layout/type fact required without leaking non-semantic source data. Adjust record layout, not direct-dependency semantics. 2. **Generated C seed.** Measure generated `ww0.c` size, C99 portability, host-C variance, and fixed-point convergence on at least three unrelated C implementations. Restrict/repair the recovery emitter rather than introducing a second maintained compiler or opaque-permanent binary seed. 3. **External linker/tool bundles.** Certify deterministic debug info, build ID, archives, scripts, shared-loader metadata, redistribution rights, and resource closure. Change tool adapters/bundle membership if needed; do not restore ambient driver defaults. 4. **Sandbox portability.** Implement denial conformance on every official B platform, including process children, filesystem race/symlink attacks, clock, randomness, and network namespaces. A platform that cannot enforce it remains non-frozen rather than gaining an undeclared exception. 5. **Native-provider coverage.** Exercise ELF first, then Mach-O frameworks/SDKs, PE/COFF import libraries, symbol versioning, and kernel image builders. Extend the closed typed schema by version where genuinely required; do not add raw search or a general build language. 6. **Registry/private-source protocol.** Test mirror failover, redirects, credential isolation, key rotation, provenance, yanked releases, and malicious archives. Vendored/exact-origin operation remains the deterministic fallback. 7. **Performance.** Validate compiler worker strategy and CAS hashing against the measured 15-package/full-toolchain budgets. Process topology may change while action boundaries and keys remain fixed. ### 15.6 Final decision trace The documented Pike evidence shapes the design: computable direct dependencies, fast compilation, cycle rejection, package boundaries, and orthogonal concepts; the collective Plan 9 papers add transparent encodings and system-wide placement of complexity. Later Go work demonstrates one possible module/cache/toolchain evolution but does not decide WW's answer. This document then applies those principles to requirements early Go's package/build model did not expose completely: foreign ABI contracts, C headers, external assembly and objects, archive/link ordering, linker scripts, CRT/libc/sysroot identity, host generators, and explicit build/host/target closures. The resulting binding conclusion is singular: **replace the current system with WW Action Build exactly as specified above**. Do not preserve the old path, and do not substitute a programmable project framework or a source-only package command during implementation.