RESULT_MAX was written down twice, once in flan_dev.c and once in the agent, with a run-time check that the two had not drifted. That second copy was a buffer sized to be sent through a socket, and it is gone: the agent asks flan_dev_result_cap() and allocates, which it can do because it is never the game thread. The bound itself stays, and the reason is the rule everything else here is built around. result is what the game thread writes into, from a render thunk at a frame boundary; a growable one is the frame thread calling realloc, which is an allocation in the one place this design exists to keep allocation out of. It would also break the seqlock, which is a protocol about torn contents and assumes the address it copies from neither moves nor goes away underneath the reader. Growing on the writer's side is a use-after-free the counter cannot see. So it is a render budget and not a wire size, and it only looked like one because the agent had a copy of it. Removing the bound is a redesign of the read -- probe, allocate, re-read, validate, retry -- and belongs with moving the read to a frame boundary. Also: flan_agent_request answers "err path too long" where the socket does, instead of nothing. One verb table is only worth having if the two callers cannot be told apart. The measurement table in BUILT.md is retaken back to back across all four shapes, because this machine drifts by more than the thing being measured. The internal socket was ~41us of a 21ms redefinition; --two-process is unchanged and is not slower than the merged build in any column.
Description
Languages
OCaml
67.2%
Emacs Lisp
15.2%
C
10.4%
HTML
2.9%
Standard ML
2.8%
Other
1.5%