docs: resolve WWAR protocol contradictions

Make the schema-1 transcription mechanically consistent before the protocol freeze: restore compiler-protocol identity, use the typed native-contract record identity, distinguish encoding and path classes, and close the package artifact kinds. These corrections must land together because one exhaustive IDL cannot encode the prior conflicting rules.
This commit is contained in:
2026-08-10 15:48:54 +09:00
parent 6880ebe543
commit 90afbb1c2e

View File

@@ -579,9 +579,11 @@ integer overflow, and a comment marker inside an unclosed string are errors.
Whitespace, comments, assignment order, record-key order, and clause order where
the schema declares identity keys are non-semantic. List order is semantic.
Parsing produces a typed record and its semantic digest is the WWAR encoding of
that record, not the original text. `ww fmt` writes two-space canonical text;
generated lock/vendor files MUST already equal that rendering in frozen mode.
Parsing produces a typed record whose canonical semantic encoding is
`WWAR(record)`, not the original text. Its semantic digest is the applicable
kind/schema-bound `record_id` from section 6.6. `ww fmt` writes two-space
canonical text; generated lock/vendor files MUST already equal that rendering
in frozen mode.
## 5. Build model and graph construction
@@ -847,20 +849,31 @@ Schema defaults are always encoded, so no semantic field is inferred from
absence. Floats, signed integers, null, and indefinite lengths do not exist.
One byte string/string is at most `2^31-1` bytes, a container has at most
`2^24-1` members, and nesting depth is at most 64. A logical path string uses `/`,
has no NUL/backslash/absolute prefix, empty/`.`/`..` segment, and passes the
schema's ASCII-identity or NFC-source-path rule. These are protocol limits, not
host `size_t` limits. Human-readable JSON is a lossless rendering, not the
hashed representation. Phase-0 golden vectors include empty/nested records,
ordered lists, sorted maps, every rejection, and their complete bytes/digests.
`2^24-1` members, and nesting depth is at most 64. A content/container-relative
logical path string uses `/`, is relative, has no NUL/backslash, empty/`.`/`..`
segment, and passes the schema's ASCII-identity or NFC-source-path rule. A field
that explicitly permits `.` as its complete root sentinel is the sole exception.
These are protocol limits, not host `size_t` limits. Human-readable JSON is a
lossless rendering, not the hashed representation. Phase-0 golden vectors
include empty/nested records, ordered lists, sorted maps, every rejection, and
their complete bytes/digests.
The normative empty-record vector is
`57574152000107000000000000000400000000`, SHA-256
`138c6acb7f01e91df73cb1d9c3356d18f19d7b8eb8b0a15426bef32e515d0de0`.
Path values in WWAR are normalized logical slash paths. Absolute paths,
filesystem device/inode numbers, mtimes, cache locations, and command process IDs
are invalid fields. A physical input enters only through a logical name, content
digest, type, and semantic mode.
Each schema assigns every path field a path class. Artifact, source, generated
output, install-destination, bundle-relative, sysroot-relative, and
vendor-relative paths use the relative rule above. Sandbox-execution paths are
path-independent absolute paths only in the closed virtual namespaces `/work`,
`/in`, `/out`, `/tool`, and `/data`; schema-1 action working directory is exactly
`/work`, and exact sandbox path spellings in argv are encoded. Platform-validated
target-runtime paths are a separate type and may be absolute in H's namespace.
Workspace locations and observation physical paths are separately typed and
never enter an artifact action record or key as host locations. Absolute host
paths, filesystem device/inode numbers, mtimes, cache locations, and command
process IDs are invalid in action templates and final action records. A physical
input enters only through a logical name, content digest, type, and semantic
mode.
### 6.2 Required action-record fields
@@ -876,10 +889,11 @@ Every record contains, in this order:
acquisition but unused targets/tools do not invalidate this action;
5. profile fields: optimization, debug, assertions, overflow, panic, sanitizers,
LTO, relocation/code model, symbol stripping, and reproducibility policy;
6. logical package/product/action identity and logical working directory;
6. logical package/product/action identity and sandbox-virtual working directory
(schema 1 exactly `/work`);
7. exact argument vector and a sorted literal environment map;
8. byte-sorted named inputs, each with edge kind, logical path, file/tree type,
semantic mode, content digest, and—where applicable—origin package identity;
8. byte-sorted named inputs, each with edge kind, logical path, semantic artifact
kind, semantic mode, content digest, and—where applicable—origin package identity;
9. direct export-data inputs byte-sorted by package identity for `ww.package`
actions;
10. selected source-membership list and target-selection explanation;
@@ -918,7 +932,8 @@ A `ww.package` action consumes:
- their ordered membership metadata;
- only the `.wwe` artifacts of direct imported packages;
- the compiler/backend and toolchain resources;
- B/H/T, target descriptor, profile, language/export/object/runtime protocols;
- B/H/T, target descriptor, profile, language/compiler/export/object/runtime
protocols, and manifest/lock schemas;
- package-specific native-provider declarations; and
- its literal built-in environment and sandbox policy.
@@ -1129,13 +1144,22 @@ record. Its tags are: 1 namespace (`source`, `generated`, `package`, `toolchain`
`provider-output`, or `cas`); 2 owner identity (empty only for a root source);
3 normalized logical name/path; 4 semantic artifact kind (`file`, `tree`,
`object`, `archive`, `shared`, `import-library`, `script`, `crt`, `loader`,
`native-sidecar`, or `native-abi`);
`native-sidecar`, `native-abi`, `export`, or `package-link`);
5 optional expected `TypedDigestV1`; and 6 mode (`data` or `executable`). A local
source may omit tag 5 because analysis hashes it. A `cas`, external prebuilt,
toolchain, or sysroot reference must include it. A generated/package/provider
output gets its digest only from the declared predecessor output. Absolute host
paths are invalid.
`InputSlotRefV1`, `TemplateInputV1`, `ResolvedInputV1`, built-in/template/final
action-output records, and `ResultOutputV1` use that same closed semantic
artifact-kind enum; `GenerateDecl.OutputDecl` remains restricted to `file` or
`tree`. In schema 1, `file`, `object`, `archive`, `shared`, `import-library`,
`script`, `crt`, and `loader` require a blob digest. `tree` requires record kind
1, `native-sidecar` kind 15, `native-abi` kind 16, `export` kind 18, and
`package-link` kind 19, each at record schema 1. Any other digest domain, record
kind, or schema is invalid kind substitution.
`InputSlotRefV1` has tag 1 slot name and tag 2 expected semantic artifact type.
A final action record contains no `ArtifactRefV1`: every artifact-bearing field is recursively lowered
to an `InputSlotRefV1`. `TemplateInputV1` tags are 1 unique slot name, 2 edge
@@ -1209,11 +1233,11 @@ A profile is toolchain data, not an open project map:
|---|---|---|
| 1 | schema | `1` |
| 2 | kind/version | exact built-in kind or generate version |
| 3 | protocol record | language/export/object/runtime/manifest/lock |
| 3 | protocol record | language/compiler/export/object/runtime/manifest/lock; compiler protocol is distinct from compiler/backend byte identity |
| 4 | platform roles | B, H, optional T descriptor refs |
| 5 | selected tool closure | identity plus semantic closure digest/resources |
| 6 | profile | complete `ProfileV1` |
| 7 | logical identity/cwd | normalized, path-independent |
| 7 | logical identity/cwd | normalized identity; cwd exactly `/work`, path-independent |
| 8 | argv | ordered strings |
| 9 | environment | sorted literal map, no secrets |
| 10 | input slots | sorted `(name, edge kind, producer/output or source ref, type, mode)` |
@@ -1284,9 +1308,10 @@ float ABI; CPU baseline; required feature set; forbidden feature set; minimum
SDK; relocation; code model; PIC requirement. Empty scalar/set means no
constraint. Matching is exactly section 8.4; no expression field exists.
`ToolchainV1` tags are: 1 schema; 2 ID; 3 version; 4 protocol record; 5 sorted
`Tool` records; 6 sorted platform descriptors; 7 sorted profiles; 8 sorted link
policies; 9 runtime/provider records; 10 bundle tree digest/signature provenance.
`ToolchainV1` tags are: 1 schema; 2 ID; 3 version; 4 the same complete protocol
record used by action tag 3; 5 sorted `Tool` records; 6 sorted platform
descriptors; 7 sorted profiles; 8 sorted link policies; 9 runtime/provider
records; 10 bundle tree digest/signature provenance.
A `Tool` is `(name, bundle-relative path, executable blob digest, ordered dynamic
tool dependencies, resource-tree digests, adapter record)` tags 16. A link
policy is `LinkPolicyV1`: tag 1 product-platform descriptor; 2 product kind; 3
@@ -1373,9 +1398,9 @@ record. In a resolved action, those records and every artifact field above are
`InputSlotRefV1` values; source/action/provider output digests live only in
action tag 10. A sidecar's internal artifact digest must equal the corresponding
object/archive/shared input-slot digest, and its contract digest must equal the
referenced native-ABI input record. Section/layout/provenance digests inside a
sidecar are verification facts, not locators from which the action may read
undeclared content.
kind-16 `TypedDigestV1` of the referenced native-ABI input record.
Section/layout/provenance digests inside a sidecar are verification facts, not
locators from which the action may read undeclared content.
| Tag | `NativeABIContractV1` field | Rule |
|---|---|---|
@@ -1389,9 +1414,12 @@ undeclared content.
| 8 | minimum-platform | optional `PlatformVersionV1` |
| 9 | code | `NativeCodeContractV1` |
Its identity is
`SHA256("WW-NATIVE-ABI-CONTRACT-V1\0" || u64be(length) || WWAR(contract))`.
WW computes it; a supplied digest is never accepted in place of the record.
Its typed record identity is `record_id(16, 1, contract)` as defined in section
6.6. Every schema-1 digest identifying a complete `NativeABIContractV1` is the
corresponding record-domain, kind-16, schema-1 `TypedDigestV1`. WW computes it; a
supplied digest is never accepted in place of the record. Subordinate layout,
calling-convention, type-contract, and header-contract digests remain their
separately specified semantic values.
| Tag | `NativeABIPlatformV1` field | Rule |
|---|---|---|
@@ -1565,7 +1593,9 @@ referenced init symbol against section garbage collection.
`.wwe` is a cache/build protocol, not source text and not a long-term binary
distribution promise. It starts with the eight-byte magic `WWEX\0\0\0\1` and a
WWAR-encoded body containing:
WWAR-encoded body. The magic is fixed framing that is reconstructed and verified
around the body; it does not create a second blob identity. The typed `.wwe`
identity is `record_id(18, 1, ExportV1)` over that body. The body contains:
1. export schema, language edition, type-system protocol, and required reader
capabilities;
@@ -1712,7 +1742,8 @@ An immutable toolchain bundle has a canonical `toolchain.wwt` descriptor with:
ww-toolchain 1
id = "ww.org/toolchain"
version = "v1.4.0"
protocols = { language = "1", export = "1", object = "1", runtime = "1" }
protocols = { language = "1", compiler = "1", export = "1", object = "1",
runtime = "1", manifest = 1, lock = 1 }
tool "wwc" { path = "bin/wwc", digest = "sha256:..." }
tool "cc" { path = "bin/clang", digest = "sha256:..." }