fix: ignore hidden named source operands

This commit is contained in:
2026-08-22 19:28:54 +09:00
parent 6279d46652
commit 3922f1c34e
6 changed files with 627 additions and 0 deletions

View File

@@ -9955,6 +9955,131 @@ 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 29032918](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 32443315](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 886914](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 14381509](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L1438-L1509)).
A package with no remaining source category returns `NoGoError`
([lines 10761082](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 250270](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 697728](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 703719](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 10151050](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 1123](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 111](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 2838](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/os/stat_unix.go#L28-L38),
[`os/stat_linux.go`, lines 1330](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.
## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins.

View File

@@ -319,6 +319,22 @@ ImportPath = ident { "." ident } .
delegated graph-import scan or tools. An ordinary build compares production
names only; one test product compares its production, same-package test, and
external-test selections without merging their units.
- A single existing raw `.ww` operand is also subject to the unconditional
leading-name rule: if its final requested basename begins `.` or `_`, it is
ignored before the source is opened. Named raw sources otherwise retain their
existing all-files behavior, so a visible wrong-platform suffix remains
eligible. Only the requested basename participates: a hidden parent does not
hide visible `main.ww`, a hidden symlink spelling stays hidden for any
existing non-directory target, and a visible symlink spelling stays eligible.
The excluded operand creates no package, declaration, import binding/edge,
action, artifact, initialization, test,
publication, or persistent state. `ww build` reports the existing
`directory contains no WW package sources` condition; an explicit running
raw `ww test` also emits its command-owned `FAIL`, while `-c` and `-S` do not.
This rule does not add multiple named-source package support, does not change
visible `*_test.ww` handling, and does not apply to logical operands,
directory/recursive requests, imports, or `ww run`. The diagnostic parent is
presentation metadata and never canonical identity.
- `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

View File

@@ -219,6 +219,26 @@ every `-j` level, and `-j 1` — the default — matches the former sequential
run loop exactly. Measured on the 31-package `lib/...` walk:
7.0s sequential, 2.4s at `-j 4`.
The raw single-source compatibility route applies package-source eligibility
before it invokes the compiler or harness. An existing operand ending `.ww`
whose final requested basename begins `.` or `_` is ignored exactly as it is by
directory discovery, even when the name also ends `_test.ww`; the file is not
opened and cannot contribute a test descriptor, package declaration, import,
variant, graph action, diagnostic, artifact, retained binary, or persistent
state. A normal explicit running request exits 1 with exact `FAIL\n` stdout and
the driver's `directory contains no WW package sources` stderr; `-c` and `-S`
omit the final marker. Visible wrong-platform raw names remain eligible, and
only the requested basename matters for symlinks (including non-regular
targets) and hidden parent directories.
CLI/target and the existing raw package-option shape retain precedence. Cold
rejection creates no work or temporary product; warm rejection preserves prior
work and public bytes without transaction residue. The focused
`named_source_prefixes_are_ignored` package observer proves these rules in both
driver stages, including malformed/import precedence, prefix-before-test and
platform classification, symlink spelling, output rollback, residue, and
diagnostic/artifact parity. Directory package coordination and test process,
filter, timeout, signal, and descendant topology are unchanged.
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