build: route .ww directories as packages
This commit is contained in:
@@ -10244,6 +10244,138 @@ 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.
|
||||
|
||||
## 12. Candidate architectures and hard-gate decision
|
||||
|
||||
Five candidates were developed as coherent systems, not as feature bins.
|
||||
|
||||
38
docs/spec.md
38
docs/spec.md
@@ -358,6 +358,22 @@ ImportPath = ident { "." ident } .
|
||||
symbol, `.wwi`, publication, or persistence identity. Build workdir format
|
||||
remains 18, test workdir format remains 19, and semantic storage format
|
||||
remains 3.
|
||||
- A local literal passed to `ww build` whose requested final basename ends
|
||||
`.ww` remains a directory request when ordinary `stat` reports a directory,
|
||||
including when the spelling is a symlink or ends `_test.ww`. The directory
|
||||
target therefore bypasses raw named-source prefix and test-source
|
||||
classification and enters ordinary directory enumeration. Actual eligible
|
||||
production entries, package declarations, imports, graph actions, producers,
|
||||
output policy, publication, persistence, invalidation, rollback, and cleanup
|
||||
are exactly those of the existing directory package route. The requested
|
||||
spelling and physical target are loader/presentation metadata only and create
|
||||
no new package, dotted-import, graph, action, symbol, artifact, `.wwi`,
|
||||
publication, or persistence identity. Raw `ww test`, `ww test -c`, and
|
||||
`ww test -S` already use the same directory classification and are unchanged.
|
||||
`ww run` retains its separate named-operand front door. Multiple operands,
|
||||
recursive and logical requests, regular and non-regular source targets, and
|
||||
dangling symlinks are not changed. Build workdir format remains 18, test
|
||||
workdir format remains 19, and semantic storage format remains 3.
|
||||
- `import acme.codec;` loads the canonical package `acme.codec`. If that
|
||||
package declares `package wire;`, the importing file sees its exported names
|
||||
as `wire.Name`; `codec.Name` is not an additional binding. An explicit alias
|
||||
@@ -465,14 +481,24 @@ ImportPath = ident { "." ident } .
|
||||
the action list; non-main command dependencies retain ordinary actions, and
|
||||
a selection containing no command rejects before tools or output creation.
|
||||
A raw command-line `.ww` source uses its source basename without `.ww`, and
|
||||
a raw non-main source is the same no-command rejection. Missing
|
||||
trailing-slash hierarchies are created transactionally from `0777`, filtered
|
||||
by the caller's umask.
|
||||
a raw non-main source is the same no-command rejection. An existing
|
||||
directory whose requested basename ends `.ww` is not such a raw source: it
|
||||
retains directory-package output naming. With no `-o`, its requested leaf
|
||||
is used verbatim (for example, `directory_test.ww`); with an existing
|
||||
output-directory `-o`, publication instead uses the canonical selected
|
||||
target leaf (for example, `directory-target`).
|
||||
Missing trailing-slash hierarchies are created transactionally from `0777`,
|
||||
filtered by the caller's umask.
|
||||
Loading and package/import diagnostics precede no-main, derived-path,
|
||||
duplicate-destination, implicit-default, and other output preflight; all of
|
||||
those checks precede creation. Producer failure or interruption preserves
|
||||
existing directory contents and removes only request-created prefixes and
|
||||
stages. A non-directory output retains the single-product file/archive rule.
|
||||
those checks precede creation. Producer failure and coordinator-owned
|
||||
interruption preserve existing directory contents and remove only
|
||||
request-created prefixes and stages. Direct external `SIGTERM` of a build
|
||||
driver is a verified-open exception: both stages preserve public and
|
||||
committed work bytes and reap their process group, but may leave `.new`
|
||||
staging files that make a later persistent-work request reject until those
|
||||
files are removed. A non-directory output retains the single-product
|
||||
file/archive rule.
|
||||
If a lone
|
||||
command's synthesized default basename already names a directory, loading
|
||||
and graph validation complete and the build rejects before tools without
|
||||
|
||||
@@ -265,6 +265,26 @@ directory/recursive selection, package/import identities, graph/action
|
||||
identities, persistence formats (build 18, test 19, semantic 3), and test
|
||||
process topology are explicit non-effects.
|
||||
|
||||
An existing local directory whose requested build basename ends `.ww`
|
||||
(including a visible `_test.ww` symlink to a directory) remains a directory
|
||||
package, not a raw named test source. WWstage `ww build` now uses the same
|
||||
symlink-following requested-kind decision as Cstage and enters the established
|
||||
directory coordinator. The directory's actual `*_test.ww` entries remain
|
||||
excluded from production and available to `ww test`; the requested suffix does
|
||||
not itself create a test variant. Raw `ww test`, `test -c`, and `test -S` were
|
||||
already stat-routed and do not change. The focused package observer directly
|
||||
measures Cstage/WWstage build diagnostics and semantic/public artifact-byte
|
||||
parity, direct and symlinked `.ww` directories, a dotted dependency, output
|
||||
modes, cold/warm transaction behavior, compiler and signaled-linker failure
|
||||
preservation, selected-route concurrency, cleanup, and the exact test-command
|
||||
behavior. Direct driver interruption remains owned by the unchanged directory
|
||||
machinery and is not claimed fixed here. The shared resolver and `ww run` are
|
||||
deliberately unchanged—and the observer
|
||||
retains their pre-existing stage difference—because pinned Go's run command
|
||||
has a distinct named-file front door.
|
||||
No test product, result, package/import identity, or serialized format changes;
|
||||
build remains 18, test remains 19, and semantic storage remains 3.
|
||||
|
||||
List mode uses that same product process and initialization boundary but starts
|
||||
no per-test child. The shared language harness emits only selected qualified
|
||||
test names, one per line in descriptor order. A valid filter selecting no tests
|
||||
|
||||
Reference in New Issue
Block a user