run: reject .ww directories as named sources

This commit is contained in:
2026-08-23 01:07:07 +09:00
parent ca0e533c13
commit 59fc76964c
6 changed files with 612 additions and 20 deletions

View File

@@ -10376,6 +10376,141 @@ 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:73112`, rejecting an `_test.go` spelling at
103109 before passing the named set to `GoFilesPackage`.
`cmd/go/internal/load/pkg.go:32443289`, especially 32743281, follows
`Stat` and fatals when a named operand is a directory. Later checking,
action construction, linking, and execution at `run.go:141173` 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:137145,175183`,
`cmd/go/main.go:98100`, and `log/log.go:200245`. Official
`cmd/go/testdata/script/run_hello.txt:110`, `run_dirs.txt:120`, and
`run_set_executable_name.txt:417` anchor the named-file run front and its
distinction from package-form run. Indirect official directory-kind anchors
are `list_ambiguous_path.txt:415,2936`,
`mod_get_go_file.txt:4758`, and `mod_symlink_dotgo.txt:49`. 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_<pid>` 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.
## 12. Candidate architectures and hard-gate decision
Five candidates were developed as coherent systems, not as feature bins.