A 33-agent audit compared every .live Zig action's reply against the Swift arm the seam (#103) now displaces: 80 actions, 61 observable differences, each confirmed by two independent refuters.
The eight that changed what a page observes were fixed in #105 and #110 — wrapper shapes, the Siri duplicate key, recognizeText, saveHealthWorkout, badge authorization. This issue is the remaining ~38, which were left alone deliberately.
They are all the same shape: Zig is stricter than the spec.
- rejects strings containing an embedded NUL, where Swift silently truncates at the NUL
- validates filenames against
/,.and.., where Swift joins the page's string straight ontodocumentsPath - refuses a second overlapping picker call, where Swift overwrites the shared
pendingCallbackIdand abandons the first caller - refuses a non-numeric
startDate, where Swift'sas? Doubleyields nil and silently uses a default window - rejects a malformed
data:URL before writing, where Swift writes a truncated file and resolves
Every one of these is Zig declining to do something the spec does badly. Several are security-relevant — the filename one is path traversal.
The question
They are still divergences. A page written against the spec can observe them, and "the migration made my app stricter" is a real thing to be surprised by, even when the strictness is right.
- Keep them — document each in the module that makes the choice, and note the class in the SDK docs so it is discoverable rather than a surprise at runtime.
- Match the spec exactly — much larger, and it means reintroducing a path traversal on purpose. I would argue against.
My read is keep-and-document, but it is a product call about a published surface, not a mechanical one, which is why this is an issue rather than a PR.
The full per-action list is in the audit output; I can paste any subset into this issue on request.
Related: #116 and #115 are cases where the spec is the one behaving badly.