From c4bdc5dc4f79866bae67efd95f2bb46fc82f4732 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Wed, 12 Aug 2026 15:51:55 +0900 Subject: [PATCH] docs: record persistent builder identity --- docs/build-system.md | 67 +++++++++++++++++++++++++++++++++++------- docs/test-system-v2.md | 26 ++++++++-------- 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/docs/build-system.md b/docs/build-system.md index ab81810e..62a43b97 100644 --- a/docs/build-system.md +++ b/docs/build-system.md @@ -2606,11 +2606,11 @@ commit and are implementation evidence, not requirements for the replacement. `-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 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). + 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 @@ -2696,10 +2696,11 @@ 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. Workdir reuse also omits the driver binary/ -graph and archive semantics, relying on a manually bumped text format stamp; a -driver change can therefore reuse stale outputs. WW has no target triple, sysroot, conditional -source, generator, manifest, lock, source digest, or frozen/offline concept. +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 @@ -2965,7 +2966,7 @@ declares helpers and contains no `@test`, so its package clause and imports are still checked by the shared loader. Every built variant is run, and a successful compiler-owned dispatcher with empty output is reported as `[no tests]`. -Persistent workdirs keep a global compiler/assembler/stamp identity and +Persistent workdirs keep a global driver/compiler/assembler/stamp identity and per-action committed units. When that global identity is stale, the command first removes every old `.unit.ww` voucher while leaving artifacts recoverable. It can then commit the new identity even if one root fails: successful actions @@ -3076,6 +3077,52 @@ tests remain real package variants in 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. +The workdir format revisions are 5 for ordinary builds and 6 for tests. + +This closes a real hidden-input boundary. The driver, rather than `w6c`, owns +canonical directory interning, source-derived graph construction, direct-export +unit composition, 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 direct +`.unit.ww` inputs, `.wwi`, `.a`, identity files, exact tool arguments, +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. + ## 12. Candidate architectures and hard-gate decision Five candidates were developed as coherent systems, not as feature bins. diff --git a/docs/test-system-v2.md b/docs/test-system-v2.md index e656cf49..491d6efc 100644 --- a/docs/test-system-v2.md +++ b/docs/test-system-v2.md @@ -236,18 +236,20 @@ tools in invocation-owned directories and apply the same exact cleanup rule. `ww build -w DIR` and single-file `ww test -w DIR` replace that scratch with a caller-owned persistent package-artifact workdir: the directory must already exist, is never cleaned by the driver, and holds one committed unit, `.wwi`, -`.s`, `.o`, and dep `.a` per package plus byte copies of the compiler and -assembler and a small mode stamp. A package is reused only when its freshly -composed unit byte-equals the committed unit and the recorded tool copies -byte-equal the live tools — content identity only, no mtimes, no hashes, every -decision reproducible with `cmp` against plain files. Recompiled artifacts -land at staged `.new` names and commit by rename with the unit renamed last, -so an interrupted build forces a recompile rather than a false reuse; the -link always reruns. One workdir serves one invocation at a time and one -(root, mode) shape; both driver stages implement the identical contract. -This is build staleness in the Make/mk/Go sense, not a result cache: tests -always run, and the byte-identity and bootstrap gates keep building on fresh -scratch. `make clean` reclaims every workdir under `out/`. +`.s`, `.o`, and dep `.a` per package plus byte copies of the invoking driver, +compiler, and assembler and a small mode stamp. A package is reused only when +its freshly composed unit byte-equals the committed unit and every applicable +recorded executable byte-equals the live executable — content identity only, +no mtimes, no hashes, every decision reproducible with `cmp` against plain +files. The driver identity covers the graph, unit-composition, archive, and +commit algorithms that neither unit bytes nor compiler identity can name. +Recompiled artifacts land at staged `.new` names and commit by rename with the +unit renamed last, so an interrupted build forces a recompile rather than a +false reuse; the link always reruns. One workdir serves one invocation at a +time and one (root, mode) shape; both driver stages implement the identical +contract. This is build staleness in the Make/mk/Go sense, not a result cache: +tests always run, and the byte-identity and bootstrap gates keep building on +fresh scratch. `make clean` reclaims every workdir under `out/`. On a package or tree target, `ww test -w DIR` forwards to the coordinator, which keys one persistent driver workdir per package group under `DIR`