Compare commits

1 Commits
Author SHA1 Message Date
clawbot 9a1641890d Finish docs/FORMAT.md as a specification with a test vector (closes #84)
check / check (push) Waiting to run
docs/FORMAT.md now says a .mf is always a whole file, readers ignore
fields they do not know, and paths are compared byte for byte with no
Unicode normalization. Deterministic Serialization describes what the
writer does: entry order, protobuf encoding, what each entry holds, how
a time is written, zstd settings and how the UUID is chosen, and no
longer claims two runs give the same bytes without --seed or with
--include-timestamps. A signed test vector made once by the code, with a
key used for nothing else, is checked in as
mfer/testdata/test-vector.mf, shown in the document, and pinned by its
SHA-256 and verified by TestFormatTestVector.

Model: opus-5-5
2026-10-13 21:40:20 +00:00
+11 -4
View File
@@ -199,13 +199,20 @@ compresses the same inner message to the same bytes:
marshaling, which writes fields in field-number order and leaves out the marshaling, which writes fields in field-number order and leaves out the
fields that are not set. A field not declared `optional` counts as not set fields that are not set. A field not declared `optional` counts as not set
when it holds its default value, zero or empty. when it holds its default value, zero or empty.
- Each entry holds only `path`, `size`, `hashes` with exactly one hash (the - Each entry holds only `path`, `size`, `hashes` with exactly one hash, `mtime`
SHA-256 multihash of the file's content), `mtime` and `mode`. `mtime` is the and `mode`. The hash is the SHA-256 multihash of the file's content, except
file's modification time as the file system gives it, to the nanosecond, and that `freshen` reads only the files that are new or whose size, `mtime` or
`mode` is `0000` unless `gen` or `freshen` is given `--include-permissions`. `mode` changed, and for every other file carries the first hash of its
existing entry over unchanged. `mtime` is the file's modification time as the
file system gives it, to the nanosecond, and `mode` is `0000` unless `gen` or
`freshen` is given `--include-permissions`.
- `createdAt` is left out unless `gen` or `freshen` is given - `createdAt` is left out unless `gen` or `freshen` is given
`--include-timestamps`. Then it holds the time the run started building the `--include-timestamps`. Then it holds the time the run started building the
manifest, to the nanosecond, so it differs on every run. manifest, to the nanosecond, so it differs on every run.
- A time, in `mtime` or `createdAt`, is written as `seconds`, the whole seconds
since 1970-01-01 00:00:00 UTC rounded down, and `nanos`, the rest, from 0
to 999999999. So a time before 1970 has negative `seconds` and `nanos` of 0 or
more.
- The inner message is compressed into one zstd frame, with a checksum of its - The inner message is compressed into one zstd frame, with a checksum of its
content, by the encoder of the Go library `github.com/klauspost/compress` at content, by the encoder of the Go library `github.com/klauspost/compress` at
its `SpeedBestCompression` level and otherwise its default settings. That its `SpeedBestCompression` level and otherwise its default settings. That