Artifact 959d136e85ac7a35de6344ec3efafdbc3dde51a2f6e219850cde8b85548de9bf:
- File
docs/RELEASE-NOTES-0.3.21.md
— part of check-in
[575cd3fcdd]
at
2026-09-17 19:12:48
on branch trunk
— Release 0.3.21
A multi-check-in fossil push lands; --httptrace reaches a zit server. (user: dmestas, size: 3442) [annotate] [blame] [check-ins using]
# zit 0.3.21 zit 0.3.21 accepts a stock fossil push that carries more than one check-in, and accepts the request type fossil sends under `--httptrace`. No artifact, tag namespace, or on-disk repository format changed. One server error card is new, and one request media type is no longer refused. ## A multi-check-in push lands fossil sends a batch of check-ins as one round, with each manifest a delta against the previous one. The server scans the round before it stores anything, so a rejected request leaves no trace, and the scan reconstructed each pushed delta against the committed store. A manifest delivered earlier in the same round is not committed yet. The lookup failed, and the failure was reported as a malformed file card. The consequence was that any push of two or more check-ins from a stock fossil client was refused, and the only workaround was pushing one check-in at a time, which nobody would guess. Single-check-in rounds, including ones with several file cards, were unaffected, which is why every existing interop test passed. It cost a tester two days, most of them spent on card syntax because the refusal said "malformed". The scan now parks a delta whose basis is not held and settles it once the whole round has been seen. A basis is either committed or was delivered by this round, possibly as another parked delta, so resolution runs to a fixpoint and the sender's order within the round does not matter. Whatever is still unresolved names a basis the round never carried and the store never held, and that refusal now says so: ``` error delta basis not held: TARGET against BASIS ``` Two unit tests push a delta against a basis delivered earlier and later in the same round, the second through a chain of two deltas. A new fossil interop smoke scenario clones a served zit repository with stock fossil, commits three times offline, pushes once, and checks all three check-ins are in the served store. It fails against 0.3.20. ## `--httptrace` reaches a zit server fossil's `--httptrace` sends its request uncompressed under the media type `application/x-fossil-debug`. The server refused that type with a bare 415, on the stated premise that the reference client never sends it. It does, and it is the first thing anyone reaches for when a sync misbehaves, so the diagnostic was refused in the one situation it exists for. The type is accepted. The exchange tells the request handler whether the body is a zlib container or plain cards, and the handler decodes or copies accordingly. The reply is framed as before; fossil picks the reply's framing off the reply's own content type. `application/x-fossil-uncompressed` remains reply-only and is still refused on a request. ## Compatibility - No on-disk repository or wire format changed; Fossil RFC revision 00 remains the target. - A pushed delta with no basis anywhere is refused with a new named error card in place of "malformed file line". The draft's own rule for this case is to park the delta and create a phantom; a stateless server cannot park it across requests, so the refusal stays, and now says why. - Any client's `application/x-fossil-debug` request is answered rather than refused. ## Qualification `zig fmt --check`, `zig build test`, `e2e`, `smoke` (Fossil interop against a real `fossil`, now sixteen scenarios), `muscle`, `git-import-e2e`, `git-export-e2e`, `dst`, and `cross`, plus the three-runner CI battery.