compiler: implement blank package name semantics
This commit is contained in:
@@ -6982,8 +6982,11 @@ test-runtime gap:
|
||||
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.
|
||||
Direct production, imported, and test-only probes were rejected by both WW
|
||||
stages, but only through the loader's generic `invalid or missing package
|
||||
clause`; the direct compilers also produced different syntax-recovery
|
||||
streams. Equal rejection was not semantic alignment. The gap was different
|
||||
and is completed in section 11.56.
|
||||
- **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
|
||||
@@ -10354,11 +10357,11 @@ a raw source and does not trigger the non-directory test-source omission in
|
||||
- **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.
|
||||
shell status 143 and preserve the prior public output and committed semantic
|
||||
bytes, but leave the directly spawned compiler alive and exactly three
|
||||
fixed-name `.new` files. A later persistent request rejects the existing
|
||||
`.unit.new`. That independently verified supervision/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
|
||||
@@ -10852,6 +10855,319 @@ every other package name remain ordinary.
|
||||
remains `3`; no action descriptor, cache/result record, transaction marker,
|
||||
manifest, database, or lock is added.
|
||||
|
||||
### 11.56 Implemented blank declared package-name checking
|
||||
|
||||
The exact declared name in `package _;` is now valid package-clause syntax and
|
||||
an invalid package name. Loaders retain the clause, its imports, and an
|
||||
otherwise coherent source family long enough to construct the applicable
|
||||
ordinary action; the compiler checker then reports exactly
|
||||
`invalid package name _` at the underscore token and continues checking that
|
||||
source. The underscore is accepted only in this package-name grammar slot. It
|
||||
does not become an ordinary identifier, import alias, qualifier, canonical
|
||||
package name, or successful exported identity.
|
||||
|
||||
#### Pinned authority, tests, and applicability
|
||||
|
||||
The sole authority is official Go 1.26.5 at commit
|
||||
`c19862e5f8415b4f24b189d065ed739517c548ba`:
|
||||
|
||||
- **behavior directly implemented or asserted by pinned Go** — the compiler
|
||||
scanner admits `_` to identifier scanning, dispatches it through the name
|
||||
path, and returns it as a name token; the parser accepts and stores that token
|
||||
in the package-name position
|
||||
([`cmd/compile/internal/syntax/scanner.go`, lines 88–107](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/scanner.go#L88-L107),
|
||||
[368–394](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/scanner.go#L368-L394),
|
||||
and
|
||||
[437–439](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/scanner.go#L437-L439),
|
||||
[`parser.go`, lines 397–420](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/parser.go#L397-L420)
|
||||
and
|
||||
[2751–2763](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/syntax/parser.go#L2751-L2763)).
|
||||
The types2 checker rejects the retained node as `invalid package name _`
|
||||
and continues file initialization
|
||||
([`cmd/compile/internal/types2/check.go`, lines 336–355](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/check.go#L336-L355));
|
||||
syntax errors prevent types2 from running
|
||||
([`cmd/compile/internal/noder/noder.go`, lines 45–77](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/noder.go#L45-L77),
|
||||
[`irgen.go`, lines 23–99](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/noder/irgen.go#L23-L99)).
|
||||
- **behavior directly implemented or asserted by pinned Go** — `go/build`
|
||||
reads `_` without declaration-error parsing, classifies production and test
|
||||
roles, and records imports before cmd/go builds package actions
|
||||
([`go/build/read.go`, lines 55–56](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/read.go#L55-L56),
|
||||
[187–198](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/read.go#L187-L198),
|
||||
and
|
||||
[265–340](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/read.go#L265-L340),
|
||||
[`go/build/build.go`, lines 931–1039](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/build/build.go#L931-L1039)).
|
||||
Named files use one synthetic package loader
|
||||
([`cmd/go/internal/load/pkg.go`, lines 3244–3315](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/pkg.go#L3244-L3315));
|
||||
test synthesis augments production with internal-test files rather than
|
||||
treating them as unrelated packages
|
||||
([`cmd/go/internal/load/test.go`, lines 175–226](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/load/test.go#L175-L226)).
|
||||
- **behavior directly implemented or asserted by pinned Go** —
|
||||
[`test/blank1.go`, lines 1–31](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/test/blank1.go#L1-L31)
|
||||
asserts the blank-name error plus later checker errors, directly proving
|
||||
continued checking.
|
||||
[`internal/types/testdata/check/blank.go`, lines 1–5](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/internal/types/testdata/check/blank.go#L1-L5)
|
||||
separately asserts only the blank-name error. Official role controls
|
||||
[`build_test_only.txt`, lines 1–18](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_test_only.txt#L1-L18)
|
||||
and
|
||||
[`build_no_go.txt`, lines 1–30](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_no_go.txt#L1-L30)
|
||||
anchor the surrounding test-only selection rules. The pinned repository has
|
||||
no official cmd/go test matrix for named, multiple, mixed,
|
||||
test-only, artifact, rollback, concurrency, or interruption forms of
|
||||
`package _`; those are WW-native proofs, not attributed to an absent Go
|
||||
script.
|
||||
- **behavior directly implemented or asserted by pinned Go** — after primary
|
||||
syntax succeeds, types2 validates the imported package object's name before
|
||||
consulting a local alias. Name `_` reports
|
||||
`could not import PATH (invalid package name: "_")` at the import path;
|
||||
an empty name instead quotes the actual empty value as
|
||||
`invalid package name: ""`. The resolver
|
||||
installs and caches a path-leaf-named fake package, marks the occurrence
|
||||
used, and continues checking
|
||||
([`cmd/compile/internal/types2/resolver.go`, lines 125–180 and 248–335](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/compile/internal/types2/resolver.go#L125-L180)).
|
||||
The public checker twin implements the same rule
|
||||
([`go/types/resolver.go`, lines 157–190 and 263–350](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/go/types/resolver.go#L157-L190)).
|
||||
- No official pinned test directly supplies an imported `Package` whose name
|
||||
is `_`. The two primary-source blank-name tests above do not assert this
|
||||
importer-result validation. Its imported-interface matrix is therefore
|
||||
WW-native proof grounded in the pinned resolver implementation, not a claim
|
||||
about absent official testdata.
|
||||
- **behavior derived from the pinned implementation** — the diagnostic owns
|
||||
the underscore position, normally line 1 column 9, and belongs after source
|
||||
loading, graph construction, complete-file syntax, and dependency-eligible
|
||||
producer ordering. WW has the same explicit package clause, blank token,
|
||||
syntax/check split, package families, imports, and package actions, so the
|
||||
rule applies without adding modules, manifests, registries, generalized
|
||||
imports, or a new identity model.
|
||||
|
||||
Before this slice, **directly measured WW behavior** was a generic positioned
|
||||
`invalid or missing package clause` from both public stages before any
|
||||
producer. Direct Cstage `w6c` emitted four package-clause recovery diagnostics
|
||||
while WWstage `w6c_ww` emitted three. A visible named `_test.ww` ordinary build
|
||||
was rejected at its header instead of being validated and omitted. These facts
|
||||
were a real package/build/test/import difference despite stage-equal public
|
||||
rejection. After the primary-source parser/checker repair and before the
|
||||
imported-interface completion, **directly measured WW behavior** also accepted
|
||||
an owner-matched hand-authored `.wwi` declaring `package _;`: default,
|
||||
explicit, and blank controls accepted and published usable semantic facts, and
|
||||
the explicit alias control produced successful byte-identical Cstage/WWstage
|
||||
assembly and interface output. Ordinary producers could not create that
|
||||
metadata, but direct `--import` and caller-owned persistent interfaces made the
|
||||
gap externally observable.
|
||||
|
||||
#### Semantic ownership
|
||||
|
||||
Primary package-slot syntax and marker positions remain owned by the C/WW
|
||||
parser twins `cmd/wcc/parse.c` and `lib/ww/syntax/parse.ww`; primary and
|
||||
imported blank-name checker diagnostics and fake-package resolution are owned
|
||||
by `cmd/wcc/check.c` and `selfhost/cmd/wcc/check.ww`. Imported export-data
|
||||
materialization, four-state package metadata, primary-rooted reachability,
|
||||
owner filtering, recovery qualifier assignment, and delayed concatenation are
|
||||
owned by `cmd/w6c/main.c` and `selfhost/cmd/w6c/main.ww`. Exact import-path
|
||||
token positions are private `N_USE` state owned by `cmd/wcc/ww.h`,
|
||||
`lib/ww/syntax/ast.ww`, both parser twins, and
|
||||
`lib/ww/syntax/decl.ww`.
|
||||
|
||||
The public drivers and package coordinator already supply canonical direct
|
||||
interface arguments and inherit the validation without edits. No loader,
|
||||
assembler, archiver, linker, runtime, package-identity, or import-syntax owner
|
||||
changes in this completion. This complete ownership replaces the earlier
|
||||
transitional assumption that the slice had only four syntax/checker owners.
|
||||
|
||||
#### Four-axis behavior and phase order
|
||||
|
||||
- **Build:** an eligible blank production source passes the loader, contributes
|
||||
its ordinary package action and import closure, and fails in checker entry.
|
||||
A visible literal named `_test.ww` still follows section 11.51: after its
|
||||
header and contiguous imports are valid, ordinary build omits it before body
|
||||
parsing or action construction, including when the declared name is `_`.
|
||||
`ww run` retains its earlier MainOnly boundary: a blank root is not `main`,
|
||||
so a successfully loaded root is rejected before any producer or compiler.
|
||||
- **Test:** an all-blank production, internal-test, or honest test-only family
|
||||
reaches its applicable test-package compiler action and fails there. A valid
|
||||
production `p` plus blank test `_`, or blank production `_` plus unrelated
|
||||
`p`/`p_test`, remains a coordinator family mismatch before tools. Existing
|
||||
raw/directory `FAIL` placement, compile-only empty stdout, and directory
|
||||
`-S` CLI-shape diagnostics are unchanged; no failed blank product runs.
|
||||
- **Package:** `_` is retained only as a declared source-family observation.
|
||||
It is not canonical identity. In an all-blank selected action, the checker
|
||||
emits one positioned BlankPkgName diagnostic per retained source marker in
|
||||
deterministic source-section order and continues later checking. Mixed
|
||||
declared names retain loader conflict precedence.
|
||||
- **Import:** a valid contiguous import in a blank source is a normal source
|
||||
occurrence and graph edge. Missing or invalid recursive dependencies can
|
||||
therefore fail before the parent checker. An ordinary blank source provider
|
||||
cannot publish a successful interface or archive. A reached hand-authored or
|
||||
corrupted `.wwi` that declares `_` is nevertheless parsed and defensively
|
||||
rejected by the consuming compiler; an unused interface is inert. Default,
|
||||
explicit, and blank aliases cannot mask the invalid provider name.
|
||||
Visibility, vendor, cycle, and initialization rules do not change.
|
||||
|
||||
The complete observable phase order is: source eligibility and loader-visible
|
||||
header/family checks; recursive import loading; MainOnly rejection for `run`;
|
||||
eligible dependency producers for build/test or a run root that passed
|
||||
MainOnly; the parent compiler's complete-file syntax; BlankPkgName checking;
|
||||
reached imported-package validation; later checker diagnostics; then existing
|
||||
driver/coordinator failure trailers.
|
||||
Consequently malformed contiguous imports precede graph construction, a
|
||||
missing dependency can suppress both a later body syntax error and
|
||||
BlankPkgName, and full-file syntax suppresses checker diagnostics. A blank run
|
||||
root never starts even valid dependency producers because MainOnly is earlier.
|
||||
|
||||
#### Test graph, actions, and identity boundaries
|
||||
|
||||
A production-only blank package under `ww test` has one ordinary production
|
||||
compiler action. Production `_` plus a same-package `_test.ww` also declared
|
||||
`_` forms one internal-test family: its augmented action owns both source sets,
|
||||
and `sep_recompile_for_test` substitutes it throughout the product closure, so
|
||||
the separate production node is not independently compiled for that product.
|
||||
One compiler invocation reports one BlankPkgName per retained marker. A
|
||||
test-only blank `_test.ww` forms one test-only internal action and reports once.
|
||||
A blank production plus the actually related external name `__test` passes
|
||||
family classification, but its blank production dependency fails before the
|
||||
external action, generated main, link, or runtime can complete.
|
||||
|
||||
Direct raw files retain `__root.*`; dotted directories and providers retain
|
||||
their canonical dotted package/import/action/artifact identities; production,
|
||||
internal, external, recompiled, support, and generated-main actions retain
|
||||
their existing distinctions. Physical paths, parents, source spellings, and
|
||||
symlink targets remain loader or diagnostic observations. No successful
|
||||
ordinary producer `.wwi` can advertise `_`; a supplied or corrupted `.wwi`
|
||||
that does is invalid input, not an alternate symbol, publication, or
|
||||
persistence identity.
|
||||
|
||||
#### Imported `.wwi` validation, reachability, and recovery
|
||||
|
||||
The rules in this subsection are **behavior derived from the pinned
|
||||
implementation** for WW's supported source-like export-data channel. They do
|
||||
not claim an official imported-blank fixture that does not exist.
|
||||
|
||||
Every sorted `--import CANONICAL FILE.wwi` is first read, owner-checked, and
|
||||
syntax-parsed into its own standalone AST. Interface read, owner, syntax, and
|
||||
structural import-map errors keep their existing precedence. The compiler then
|
||||
syntax-parses the primary input. Any primary syntax error returns before
|
||||
imported-package semantic validation, so it is never accompanied by the
|
||||
broken-import diagnostic.
|
||||
|
||||
After successful primary parsing and import-map application, compiler test
|
||||
mode materializes any required support `N_USE` before resolution. The node has
|
||||
the primary owner/source ID, is marked used, uses visible name `test` or the
|
||||
collision-safe reserved `__wwtest`, and is positioned at the generated primary
|
||||
root because no source path token exists. An existing equivalent primary
|
||||
occurrence prevents duplication. When no support interface is supplied, the
|
||||
node retains the established raw external-support fallback; a supplied
|
||||
blank-named support interface is validated like every source import. Reserved
|
||||
`__wwtest` preserves its compiler-selected visible spelling after valid
|
||||
resolution but cannot skip provider-name validation. Existing
|
||||
`--test-target-package` roots already require a primary occurrence and add no
|
||||
second node.
|
||||
|
||||
A metadata-only pass classifies each represented canonical package as valid,
|
||||
missing, conflicting, or invalid; invalid means its one nonconflicting real
|
||||
declared name is exactly `_`. Compiler-private placeholder packages remain
|
||||
valid recovery metadata. Reachability is seeded only by canonical primary and
|
||||
compiler-required `N_USE.usepath` occurrences, then reaches a fixed point over
|
||||
standalone interface lists. An imported use contributes an edge only when its
|
||||
owning canonical package is already reached and valid. Interface containers,
|
||||
arbitrary embedded origins, and invalid, missing, conflicting, or unreachable
|
||||
owners are never roots or traversal sources.
|
||||
|
||||
Before binding or concatenation, each standalone list is filtered to nodes
|
||||
whose canonical owner is both reached and valid. Invalid-owner, unreachable,
|
||||
and ownerless hand-authored facts are discarded. Thus an unused invalid
|
||||
interface is wholly inert even when it contains an embedded valid-origin
|
||||
section that imports the invalid path: it emits no diagnostic, installs no
|
||||
declaration or scope, contributes no output or serialized fact, and leaves an
|
||||
otherwise valid primary byte-equivalent to the no-interface control. If the
|
||||
primary independently reaches that valid origin, its retained import can then
|
||||
reach and diagnose the invalid provider. Binding runs on those filtered lists
|
||||
and the primary list before the lists are concatenated, so unreachable
|
||||
internal uses cannot manufacture missing, conflict, or invalid effects.
|
||||
|
||||
Every retained occurrence resolving to an invalid provider is marked used and
|
||||
records declared provider name `_`. A nonblank occurrence receives a recovery
|
||||
package binding using its explicit alias or, by default, the final component of
|
||||
the canonical dotted path; a blank occurrence installs no visible binding.
|
||||
The fake package has an empty scope. Qualified value, call, and type gateways
|
||||
therefore recover as the error type without missing-member,
|
||||
unknown-type/export, or calling-nonfunction cascades, while a lexically closer
|
||||
value binding still shadows the recovery qualifier normally.
|
||||
|
||||
At checker entry, immediately after primary BlankPkgName diagnostics, the
|
||||
first retained invalid occurrence of each canonical path emits exactly
|
||||
`could not import PATH (invalid package name: "_")`; later occurrences of the
|
||||
same path are deduplicated, while distinct paths diagnose in retained
|
||||
occurrence order. Independent checker diagnostics continue afterward.
|
||||
Deduplication uses canonical dotted path because WW has no Go source-directory
|
||||
import-key component. Default, explicit, and blank alias forms all position
|
||||
this diagnostic at the path's first identifier, never at an explicit alias.
|
||||
The existing alias-or-path first-spec position remains unchanged for every
|
||||
other binding diagnostic. Full parsing, imports-only parsing, and named-source
|
||||
header parsing all retain both position families.
|
||||
|
||||
Public persistent build and test actions consume the same supported interface
|
||||
channel. If a reached caller-owned committed `.wwi` is corrupted to declare
|
||||
`package _;`, the consumer compiler fails after primary syntax and resolution;
|
||||
that action's assembler and downstream archive, link, retention, or runtime do
|
||||
not complete. A package-action failure prevents generated main; a generated-main
|
||||
action that is itself the consumer performs the same validation before its own
|
||||
assembly. Raw, production, internal, external, test-only, generated-main, `-c`,
|
||||
and applicable `-S` consumer actions use the same rule. A same-named `.ww` file
|
||||
remains an import decoy rather than a provider. An
|
||||
unreferenced corrupt interface remains inert and does not invalidate or alter
|
||||
the consumer. A failing direct compiler returns status 1 with empty stdout;
|
||||
public test presentation retains its existing running `FAIL` and
|
||||
package-trailer rules, while compile-only and assembly-only forms retain empty
|
||||
stdout.
|
||||
|
||||
#### Artifacts, rollback, concurrency, parity, and formats
|
||||
|
||||
The failed primary blank action and a consumer rejecting a reached blank-named
|
||||
interface emit neither compiler assembly nor `.wwi`, so their downstream
|
||||
assembler, archiver, linker, test harness, and user runtime do not run. Valid
|
||||
dependencies or test support that precede either failure may execute their
|
||||
ordinary producers, but request rollback removes every request-owned stage and
|
||||
commits no failed generation, public product, retained test binary, unit,
|
||||
interface, assembly, object, archive, executable, stamp, or status. Direct
|
||||
named `-o`/`-I` outputs, public outputs, retained tests, and committed semantic
|
||||
bytes remain byte-identical. Restoring the exact valid source or `.wwi` bytes
|
||||
uses the existing content-identity reuse path; invalid bytes never publish a
|
||||
replacement consumer generation. Reached interface bytes already participate
|
||||
through the existing compiler input and invalidation rules; semantic validation
|
||||
adds no graph, action, or persistence key. A build-omitted named `_test.ww`
|
||||
contributes no action or invalidation key.
|
||||
|
||||
Blank-package state, imported metadata, reachability sets, deduplication, and
|
||||
fake bindings are compiler/checker-process-local. Independent concurrent
|
||||
requests cannot share diagnostics, graph state, staging, or cleanup. Normal
|
||||
failure is waited and rolled back through the existing transaction owner and
|
||||
leaves no anonymous descriptor, `.new`, `.old`, `.install`, `.wwtxn.*`,
|
||||
capture, result, request scratch, or child.
|
||||
Direct `w6c` and `w6c_ww`, and public `ww` and `ww_ww`, agree on status,
|
||||
stdout, exact path-token positions and diagnostic order, fake recovery,
|
||||
output absence, prior-byte preservation, and every comparable semantic
|
||||
dependency artifact. Producer provenance remains the established intentional
|
||||
stage difference.
|
||||
|
||||
No signal-supervision behavior changed. Direct external `SIGTERM` during a
|
||||
blocked persistent compilation still preserves prior committed/public bytes
|
||||
but can leave the spawned compiler and fixed-name `.new` staging that poisons a
|
||||
later request. That independently verified gap remains open and is not claimed
|
||||
fixed by normal BlankPkgName rollback.
|
||||
|
||||
No serialized representation changed. The full parser changes only the
|
||||
in-memory position of a blank package marker to the underscore token; outer
|
||||
file/header/import-only markers and valid package markers keep their former
|
||||
positions. Each twin's private in-memory `Node` gains only
|
||||
`usepathfile/usepathline/usepathcol`; AST enum values, AST printing, `.wwi`
|
||||
schema, build workdir format `18`, test workdir format `19`, and semantic
|
||||
storage format `3` remain unchanged. No cache, result record, manifest, action
|
||||
descriptor, transaction marker, database, or lock is added. This closes one
|
||||
coherent semantic slice across all four axes;
|
||||
it does not complete the remaining suffix-first run front, multiple named
|
||||
source packages, shared test-process state and failure topology, RE2-compatible
|
||||
flat `-run`, finite special-source handling, or external-driver interruption
|
||||
recovery.
|
||||
|
||||
## 12. Candidate architectures and hard-gate decision
|
||||
|
||||
Five candidates were developed as coherent systems, not as feature bins.
|
||||
|
||||
Reference in New Issue
Block a user