aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/connections
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-24 17:14:54 +0100
committereunhhu <[email protected]>2026-09-24 17:14:54 +0100
commitb1ce1927022d374198441afafeb27199fc8a052a (patch)
tree6021f175f4c67ed03b44240eaa2f90d846f12f6f /prototypes/connections
parentd34f9426d5317a1948f12f229439946728bc342a (diff)
downloadpure-b1ce1927022d374198441afafeb27199fc8a052a.tar.gz
pure-b1ce1927022d374198441afafeb27199fc8a052a.zip
Establish native micro runtime checkpoint
Diffstat (limited to 'prototypes/connections')
-rw-r--r--prototypes/connections/.gitignore1
-rw-r--r--prototypes/connections/Makefile251
-rw-r--r--prototypes/connections/README.md545
-rw-r--r--prototypes/connections/SOURCE_PREVIEW.md119
-rw-r--r--prototypes/connections/async-core-budget.json16
-rw-r--r--prototypes/connections/async-server-budget.json12
-rw-r--r--prototypes/connections/check.py552
-rw-r--r--prototypes/connections/check_async_server.py181
-rw-r--r--prototypes/connections/check_copy_path.py100
-rw-r--r--prototypes/connections/check_core.py74
-rw-r--r--prototypes/connections/check_document_peer.py273
-rw-r--r--prototypes/connections/check_document_server_package.py100
-rw-r--r--prototypes/connections/check_edits.py108
-rw-r--r--prototypes/connections/check_fixed_program.py159
-rw-r--r--prototypes/connections/check_fixed_server.py180
-rw-r--r--prototypes/connections/check_flat_export.py134
-rw-r--r--prototypes/connections/check_idle_wakes.py95
-rw-r--r--prototypes/connections/check_micro_memory.py106
-rw-r--r--prototypes/connections/check_mirror.py137
-rw-r--r--prototypes/connections/check_package.py209
-rw-r--r--prototypes/connections/check_policy.py188
-rw-r--r--prototypes/connections/check_profile.py82
-rw-r--r--prototypes/connections/check_service_scale.py131
-rw-r--r--prototypes/connections/check_small_scan.py54
-rw-r--r--prototypes/connections/check_source_package.py145
-rw-r--r--prototypes/connections/check_tui.py352
-rw-r--r--prototypes/connections/check_window.py553
-rw-r--r--prototypes/connections/check_write_cost.py93
-rw-r--r--prototypes/connections/compile-program.c116
-rw-r--r--prototypes/connections/core-budget.json15
-rw-r--r--prototypes/connections/core-layout.c14
-rw-r--r--prototypes/connections/document-peer.c330
-rw-r--r--prototypes/connections/edit-tui.c945
-rw-r--r--prototypes/connections/edit-window.c638
-rw-r--r--prototypes/connections/edit.c177
-rw-r--r--prototypes/connections/evaluate.c53
-rw-r--r--prototypes/connections/examples/bounded-editor.pure19
-rw-r--r--prototypes/connections/examples/editor.pure19
-rw-r--r--prototypes/connections/examples/excerpt.pure13
-rw-r--r--prototypes/connections/examples/select-text.py72
-rw-r--r--prototypes/connections/examples/selection.pure19
-rw-r--r--prototypes/connections/examples/storage.pure11
-rw-r--r--prototypes/connections/export_flat_store.py143
-rw-r--r--prototypes/connections/fixed-budget.json18
-rw-r--r--prototypes/connections/fixed-package-budget.json10
-rw-r--r--prototypes/connections/flow.c41
-rw-r--r--prototypes/connections/flow.h25
-rw-r--r--prototypes/connections/hybrid-budget.json18
-rw-r--r--prototypes/connections/hybrid-tui-budget.json12
-rw-r--r--prototypes/connections/measure-peak-rss.c43
-rw-r--r--prototypes/connections/measure_tui_latency.py101
-rw-r--r--prototypes/connections/memory-budget.json7
-rw-r--r--prototypes/connections/mirror.c145
-rw-r--r--prototypes/connections/package_native.py361
-rw-r--r--prototypes/connections/package_source.py67
-rw-r--r--prototypes/connections/paged-budget.json18
-rw-r--r--prototypes/connections/peer-budget.json12
-rw-r--r--prototypes/connections/peer-package-budget.json8
-rw-r--r--prototypes/connections/peer-server-budget.json12
-rw-r--r--prototypes/connections/profile-budget.json18
-rw-r--r--prototypes/connections/program.c374
-rw-r--r--prototypes/connections/program.h50
-rw-r--r--prototypes/connections/result.h8
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/README.md31
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/initial/native.json116
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/initial/sanitized.json116
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/initial/test-flow.c178
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/native.json116
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sanitized.json116
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/Makefile20
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/check.py317
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/flow.c41
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/flow.h25
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/server.c347
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/store.c225
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/store.h34
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/test-flow.c183
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/cli.mjs127
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/examples/direct.pure47
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/remote.mjs89
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/compiler.mjs496
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/core.wasmbin0 -> 61072 bytes
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/project.mjs47
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/runtime.mjs350
-rw-r--r--prototypes/connections/results/2026-09-23-byte-storage/verification.json52
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/README.md27
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/boundary-checks.json34
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/core.json53
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/native.json635
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sanitized.json635
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/Makefile59
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check.py551
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check_core.py74
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check_edits.py108
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/core-budget.json15
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/core-layout.c11
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/edit.c153
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/evaluate.c53
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/editor.pure19
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/excerpt.pure13
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/select-text.py72
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/selection.pure19
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/storage.pure11
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/flow.c41
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/flow.h25
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/program.c366
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/program.h44
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/result.h8
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/runtime.c273
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/runtime.h88
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/server.c372
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store-port.c44
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store-port.h6
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store.c258
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store.h44
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-fields.c153
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-flow.c183
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-program.c111
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-runtime.c285
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-splice.c172
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/cli.mjs127
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/examples/direct.pure47
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/remote.mjs89
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/compiler.mjs496
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/core.wasmbin0 -> 61072 bytes
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/project.mjs47
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/runtime.mjs350
-rw-r--r--prototypes/connections/results/2026-09-23-document-edits/verification.json32
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/README.md28
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/native.json505
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sanitized.json505
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/Makefile43
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/check.py536
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/evaluate.c48
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/excerpt.pure13
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/select-text.py72
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/selection.pure19
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/storage.pure11
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/flow.c41
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/flow.h25
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/program.c357
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/program.h39
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/result.h8
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/runtime.c265
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/runtime.h86
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/server.c368
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store-port.c39
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store-port.h6
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store.c228
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store.h37
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-fields.c153
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-flow.c183
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-program.c111
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-runtime.c285
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/cli.mjs127
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/examples/direct.pure47
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/remote.mjs89
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/compiler.mjs496
-rwxr-xr-xprototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/core.wasmbin0 -> 61072 bytes
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/project.mjs47
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/runtime.mjs350
-rw-r--r--prototypes/connections/results/2026-09-23-execution-core/verification.json30
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/README.md31
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/native.json488
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sanitized.json488
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/Makefile28
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/check.py528
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/excerpt.pure13
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/select-text.py72
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/selection.pure19
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/storage.pure11
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/flow.c41
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/flow.h25
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/program.c402
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/program.h39
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/server.c393
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/store.c228
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/store.h40
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-fields.c153
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-flow.c183
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-program.c111
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/cli.mjs127
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/examples/direct.pure47
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/remote.mjs89
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/compiler.mjs496
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/core.wasmbin0 -> 61072 bytes
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/project.mjs47
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/runtime.mjs350
-rw-r--r--prototypes/connections/results/2026-09-23-field-connections/verification.json62
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/README.md26
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/native.json98
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sanitized.json98
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/Makefile22
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/check.py306
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/flow.c41
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/flow.h25
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/server.c346
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/store.c132
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/store.h25
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/test-flow.c110
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/cli.mjs127
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/cli.test.mjs121
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/examples/direct.pure47
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/remote.mjs89
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/compiler.mjs496
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/core.wasmbin0 -> 61072 bytes
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/project.mjs47
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/runtime.mjs350
-rw-r--r--prototypes/connections/results/2026-09-23-native-connections/verification.json29
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/README.md31
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/native.json269
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sanitized.json269
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/Makefile24
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/check.py419
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/examples/excerpt.pure13
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/examples/storage.pure11
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/flow.c41
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/flow.h25
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/program.c233
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/program.h26
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/server.c385
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/store.c227
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/store.h39
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/test-flow.c183
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/test-program.c111
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/cli.mjs127
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/examples/direct.pure47
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/remote.mjs89
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/compiler.mjs496
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/core.wasmbin0 -> 61072 bytes
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/project.mjs47
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/runtime.mjs350
-rw-r--r--prototypes/connections/results/2026-09-23-prepared-connections/verification.json51
-rw-r--r--prototypes/connections/results/2026-09-24-async-effects/async-core.json55
-rw-r--r--prototypes/connections/results/2026-09-24-async-effects/default-core.json53
-rw-r--r--prototypes/connections/results/2026-09-24-async-effects/flow.json1
-rw-r--r--prototypes/connections/results/2026-09-24-async-effects/sanitized.json1
-rw-r--r--prototypes/connections/results/2026-09-24-async-http/full-check.json614
-rw-r--r--prototypes/connections/results/2026-09-24-async-http/gated.json38
-rw-r--r--prototypes/connections/results/2026-09-24-async-http/profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-async-http/sanitized.json38
-rw-r--r--prototypes/connections/results/2026-09-24-async-http/service-scale-memory.json100
-rw-r--r--prototypes/connections/results/2026-09-24-async-read-write/full-check.json614
-rw-r--r--prototypes/connections/results/2026-09-24-async-read-write/gated.json53
-rw-r--r--prototypes/connections/results/2026-09-24-async-read-write/profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-async-read-write/sanitized.json53
-rw-r--r--prototypes/connections/results/2026-09-24-async-read-write/service-scale.json100
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/policy-peer.json12
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/policy.json11
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-linux-aarch64.tar.gzbin0 -> 12966 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-linux-aarch64.tar.gz.check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-tui-linux-aarch64.tar.gzbin0 -> 32144 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-tui-linux-aarch64.tar.gz.check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-linux-aarch64.tar.gzbin0 -> 22862 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-linux-aarch64.tar.gz.check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-tui-linux-aarch64.tar.gzbin0 -> 51398 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-tui-linux-aarch64.tar.gz.check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/pure-source-preview.tar.gzbin0 -> 337937 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-atomic-policy/source-package-check.json16
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/cli-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/cli-tui-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/cli-tui.tar.gzbin0 -> 31971 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/cli.tar.gzbin0 -> 12885 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/core.json53
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/default-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/fixed-memory.json15
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/fixed-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/source-cli-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/source-cli.tar.gzbin0 -> 22454 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/tui-profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-compact-runtime/tui.json22
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range-source/pure-source-preview.tar.gzbin0 -> 324261 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range-source/source-check-linux-aarch64.json16
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/copy-path.json27
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/default-core.json53
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/default-fixed-memory.json15
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/default-fixed-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/default-functional.json636
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/default-memory.json15
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/default-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/functional.json636
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/memory.json15
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-copy-range/service-scale.json70
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/clean-peer.log43
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/clean-release.log737
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/dynamic.txt31
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/file-sizes.txt2
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/hashes.txt4
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/package-check.json19
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/package-hashes.txt3
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/peer-budget.json23
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/peer-flow.json16
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/peer-sanitized.json16
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/pure-document-linux-aarch64.tar.gzbin0 -> 316927 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/scalar-refactor.json1
-rw-r--r--prototypes/connections/results/2026-09-24-document-peer/size.txt2
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/backpressure.json61
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/final.json65
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/fixed-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/package.json14
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/parity.json43
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/peak-memory.json67
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/pure-document-fixed-http-linux-aarch64.tar.gzbin0 -> 31733 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/source-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-http/verified.json68
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/memory-final.json15
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/memory-verified.json15
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/memory.json15
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/package-final.json12
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/package.json12
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/parity-final-v2.json12
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/parity-final.json11
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/parity-reconfigured.json13
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/parity-release.json14
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/parity-verified.json12
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/parity.json10
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/profile-final.json21
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/pure-document-fixed-final-linux-aarch64.tar.gzbin0 -> 14385 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/pure-document-fixed-linux-aarch64.tar.gzbin0 -> 14386 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-program/window-regression.json1
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui-final/package.json14
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui-final/profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui-final/pty-flow.json16
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui-final/pty-sanitized.json16
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui-final/pure-document-cli-tui-linux-aarch64.tar.gzbin0 -> 33654 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui/package-cursor.json14
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui/package.json14
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui/profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui/pty-cursor-flow.json16
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui/pty-cursor-sanitized.json16
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui/pty-flow.json16
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui/pty-sanitized.json16
-rw-r--r--prototypes/connections/results/2026-09-24-fixed-tui/pure-document-cli-tui-linux-aarch64.tar.gzbin0 -> 33625 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-flat-export-source/pure-source-preview.tar.gzbin0 -> 329118 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-flat-export-source/source-check-linux-aarch64.json14
-rw-r--r--prototypes/connections/results/2026-09-24-flat-export/export-check.json27
-rw-r--r--prototypes/connections/results/2026-09-24-flat-export/export-ext4.json28
-rw-r--r--prototypes/connections/results/2026-09-24-flat-export/export-scale-1024.json27
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/app-asan.json635
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/app-release.json635
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/gtk-flow.json1
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/memory.json14
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/package-full.json21
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/package-micro.json13
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/peer.json16
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/pure-document-hybrid-authoring-linux-aarch64.tar.gzbin0 -> 114025 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/pure-document-hybrid-micro-linux-aarch64.tar.gzbin0 -> 26045 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/small-scan.json5
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/unit-asan.json1
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/unit.json1
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage-v2/write-cost.json49
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/app-asan.json635
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/app-release.json635
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/gtk-flow.json1
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/memory.json14
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/package-full.json21
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/package-micro.json13
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/peer.json16
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/pure-document-hybrid-authoring-linux-aarch64.tar.gzbin0 -> 114009 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/pure-document-hybrid-micro-linux-aarch64.tar.gzbin0 -> 26040 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/unit-asan.json1
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/unit.json1
-rw-r--r--prototypes/connections/results/2026-09-24-hybrid-storage/write-cost.json49
-rw-r--r--prototypes/connections/results/2026-09-24-idle-wake/archived-comparison.json21
-rw-r--r--prototypes/connections/results/2026-09-24-idle-wake/fixed-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-idle-wake/fixed-server-regression.json68
-rw-r--r--prototypes/connections/results/2026-09-24-idle-wake/idle.json21
-rw-r--r--prototypes/connections/results/2026-09-24-idle-wake/package.json14
-rw-r--r--prototypes/connections/results/2026-09-24-idle-wake/pure-document-fixed-http-idle-linux-aarch64.tar.gzbin0 -> 31773 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-idle-wake/reproducible-comparison.json21
-rw-r--r--prototypes/connections/results/2026-09-24-idle-wake/source-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/async-core.json55
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/async-gated.json53
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/async-server-profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/cli-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-tui-check.json16
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-tui.tar.gzbin0 -> 47419 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/cli-http.tar.gzbin0 -> 28719 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/cli-tui-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/cli-tui.tar.gzbin0 -> 31726 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/cli.tar.gzbin0 -> 12987 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/core.json53
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/default-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/document-peer-profile.json23
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/document-peer.json16
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/fixed-memory.json15
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/fixed-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/full-check.json636
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/package-reproducibility.json31
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/precompact-budget-failure.txt9
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/release.log800
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/runtime-sanitized.json1
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/service-scale.json100
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/source-cli-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/source-cli.tar.gzbin0 -> 22595 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/source-memory.json15
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/tui-profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-idle-work-binding/tui.json22
-rw-r--r--prototypes/connections/results/2026-09-24-in-process-routing/mirror-ext4.json56
-rw-r--r--prototypes/connections/results/2026-09-24-in-process-routing/mirror-sanitized.json46
-rw-r--r--prototypes/connections/results/2026-09-24-in-process-routing/mirror-tmp.json56
-rw-r--r--prototypes/connections/results/2026-09-24-micro-default/pure-source-preview.tar.gzbin0 -> 338097 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-micro-default/source-package-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-micro-package-boundary/cli-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-micro-package-boundary/cli.tar.gzbin0 -> 14692 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http.tar.gzbin0 -> 32548 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http_tui-check.json16
-rw-r--r--prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http_tui.tar.gzbin0 -> 51424 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-micro-package-boundary/cli_tui-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-micro-package-boundary/cli_tui.tar.gzbin0 -> 33761 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-micro-profile/default-host-budget.json32
-rw-r--r--prototypes/connections/results/2026-09-24-mirror-source/pure-source-preview.tar.gzbin0 -> 332792 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-mirror-source/source-check-linux-aarch64.json15
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan-final.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan-repeated.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow-final.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow-repeated.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/hybrid-gtk-flow.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/legacy-package-recheck.json14
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/legacy-package-repeated.json14
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/package-final.json14
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/package-repeated.json14
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/package.json14
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/pure-document-window-final-linux-aarch64.tar.gzbin0 -> 49746 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/pure-document-window-linux-aarch64.tar.gzbin0 -> 49722 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-fresh-buffer.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-initial.json1
-rw-r--r--prototypes/connections/results/2026-09-24-multi-document-window/window-profile.json25
-rw-r--r--prototypes/connections/results/2026-09-24-native-checkpoint/fixed-memory.json43
-rw-r--r--prototypes/connections/results/2026-09-24-native-checkpoint/fixed-tui.json24
-rw-r--r--prototypes/connections/results/2026-09-24-native-checkpoint/source-memory.json43
-rw-r--r--prototypes/connections/results/2026-09-24-native-checkpoint/source-tui.json27
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/full-package-check.json20
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-flow-final.json1
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-flow.json1
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-sanitized-final.json1
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-sanitized.json1
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/http-only-package-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/micro-memory.json14
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/micro-package-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/peer-only-package-check.json16
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-authoring-linux-aarch64.tar.gzbin0 -> 100900 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-http-only-linux-aarch64.tar.gzbin0 -> 47527 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-micro-linux-aarch64.tar.gzbin0 -> 22482 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-peer-only-linux-aarch64.tar.gzbin0 -> 49186 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-window-only-linux-aarch64.tar.gzbin0 -> 48934 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/window-authoring.pngbin0 -> 76178 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/window-budget.json25
-rw-r--r--prototypes/connections/results/2026-09-24-native-definition-authoring/window-only-package-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/build.json16
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/connection-check.json635
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/core-budget.json53
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/dependencies.txt10
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/gtk-flow.json1
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/gtk-sanitized.json1
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/size.txt6
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/stripped.txt3
-rw-r--r--prototypes/connections/results/2026-09-24-native-document-window/window.pngbin0 -> 23918 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/fixed-cli-package-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/fixed-package-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/flat-fixed-tui.json24
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/flat-package-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/flat-source-tui.json27
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/hybrid-fixed-tui.json24
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/hybrid-source-tui.json27
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/package-check.json15
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/pure-document-fixed-cli-linux-aarch64.tar.gzbin0 -> 12966 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/pure-document-fixed-cli-tui-linux-aarch64.tar.gzbin0 -> 32072 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/pure-document-flat-cli-tui-linux-aarch64.tar.gzbin0 -> 51117 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/pure-document-hybrid-cli-tui-linux-aarch64.tar.gzbin0 -> 57788 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/pure-source-preview.tar.gzbin0 -> 333925 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-save/source-package-check.json16
-rw-r--r--prototypes/connections/results/2026-09-24-native-source/pure-source-preview.tar.gzbin0 -> 325436 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-native-source/source-check-linux-aarch64.json13
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-linux-aarch64.tar.gzbin0 -> 12886 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-linux-aarch64.tar.gz.check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-tui-linux-aarch64.tar.gzbin0 -> 31965 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-tui-linux-aarch64.tar.gz.check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-linux-aarch64.tar.gzbin0 -> 22655 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-linux-aarch64.tar.gz.check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-tui-linux-aarch64.tar.gzbin0 -> 51005 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-tui-linux-aarch64.tar.gz.check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/pure-source-preview.tar.gzbin0 -> 334682 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-opaque-core/source-package-check.json15
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/app-asan.json635
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/app-release.json635
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/gtk-flow.json1
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/memory.json14
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/package-full.json20
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/package-micro.json12
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/paged-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/peer.json16
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/pure-document-paged-authoring-linux-aarch64.tar.gzbin0 -> 111765 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/pure-document-paged-micro-linux-aarch64.tar.gzbin0 -> 25456 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/unit-asan.json1
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/unit.json1
-rw-r--r--prototypes/connections/results/2026-09-24-paged-storage/write-cost.json49
-rw-r--r--prototypes/connections/results/2026-09-24-portable-peer-source/pure-source-preview.tar.gzbin0 -> 321958 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-portable-peer-source/source-check-linux-aarch64.json15
-rw-r--r--prototypes/connections/results/2026-09-24-portable-peer/client-server-linux-aarch64.json17
-rw-r--r--prototypes/connections/results/2026-09-24-portable-peer/client-server-linux-rss-regression.json17
-rw-r--r--prototypes/connections/results/2026-09-24-portable-peer/client-server-profile.json23
-rw-r--r--prototypes/connections/results/2026-09-24-portable-peer/server-only-linux-aarch64.json17
-rw-r--r--prototypes/connections/results/2026-09-24-portable-peer/server-only-linux-rss-regression.json17
-rw-r--r--prototypes/connections/results/2026-09-24-portable-peer/server-only-profile.json23
-rw-r--r--prototypes/connections/results/2026-09-24-portable-source/pure-source-preview.tar.gzbin0 -> 321399 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-portable-source/source-check-linux-aarch64.json14
-rw-r--r--prototypes/connections/results/2026-09-24-portable-tui/fixed-linux-aarch64.json24
-rw-r--r--prototypes/connections/results/2026-09-24-portable-tui/fixed-linux-rss-regression.json24
-rw-r--r--prototypes/connections/results/2026-09-24-portable-tui/source-linux-aarch64.json27
-rw-r--r--prototypes/connections/results/2026-09-24-portable-tui/source-linux-rss-regression.json27
-rw-r--r--prototypes/connections/results/2026-09-24-posix-idle/fixed-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-posix-idle/fixed-server-regression.json68
-rw-r--r--prototypes/connections/results/2026-09-24-posix-idle/package.json14
-rw-r--r--prototypes/connections/results/2026-09-24-posix-idle/pure-document-fixed-http-linux-aarch64.tar.gzbin0 -> 32346 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-posix-idle/reproducible-comparison.json21
-rw-r--r--prototypes/connections/results/2026-09-24-posix-idle/service-scale.json62
-rw-r--r--prototypes/connections/results/2026-09-24-posix-idle/source-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-prefix-find/cli-tui.tar.gzbin0 -> 32233 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-prefix-find/package-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-prefix-find/tui-profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-prefix-find/tui.json22
-rw-r--r--prototypes/connections/results/2026-09-24-release-callback/async-core.json55
-rw-r--r--prototypes/connections/results/2026-09-24-release-callback/core.json53
-rw-r--r--prototypes/connections/results/2026-09-24-release-callback/micro-package-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-release-callback/pure-document-micro-linux-aarch64.tar.gzbin0 -> 22758 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-release-callback/pure-source-preview.tar.gzbin0 -> 333037 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-release-callback/runtime.json1
-rw-r--r--prototypes/connections/results/2026-09-24-release-callback/source-package-check.json15
-rw-r--r--prototypes/connections/results/2026-09-24-server-only-package/combined-peer-package-check.json27
-rw-r--r--prototypes/connections/results/2026-09-24-server-only-package/pure-document-combined-peer-linux-aarch64.tar.gzbin0 -> 49382 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-server-only-package/pure-document-server-only-linux-aarch64.tar.gzbin0 -> 47686 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-server-only-package/server-only-package-check.json23
-rw-r--r--prototypes/connections/results/2026-09-24-signal-safe-idle/fixed-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-signal-safe-idle/fixed-server-regression.json68
-rw-r--r--prototypes/connections/results/2026-09-24-signal-safe-idle/package.json14
-rw-r--r--prototypes/connections/results/2026-09-24-signal-safe-idle/pure-document-fixed-http-linux-aarch64.tar.gzbin0 -> 32023 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-signal-safe-idle/reproducible-comparison.json21
-rw-r--r--prototypes/connections/results/2026-09-24-signal-safe-idle/service-scale-restored.json62
-rw-r--r--prototypes/connections/results/2026-09-24-signal-safe-idle/service-scale.json60
-rw-r--r--prototypes/connections/results/2026-09-24-signal-safe-idle/source-profile.json32
-rw-r--r--prototypes/connections/results/2026-09-24-source-preview/pure-source-preview.tar.gzbin0 -> 316748 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-source-preview/source-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/core.json53
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/fixed-cli-tui-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/fixed-cli-tui.tar.gzbin0 -> 31929 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/fixed-tui-profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/pure-source-preview.tar.gzbin0 -> 318619 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/source-check.json13
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/source-cli-tui-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/source-cli-tui.tar.gzbin0 -> 50942 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/tui-profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-source-tui/tui.json25
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/cli-check.json12
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/cli-http-tui-check.json16
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/cli-http-tui.tar.gzbin0 -> 53385 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/cli-tui-check.json14
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/cli-tui.tar.gzbin0 -> 35642 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/cli.tar.gzbin0 -> 14706 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/sanitized.json22
-rw-r--r--prototypes/connections/results/2026-09-24-terminal-document-list/tui.json22
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/latency-baseline.json176
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/latency-current.json176
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/package-http-tui.json16
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/package.json14
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/profile.json21
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/pty-flow.json19
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/pty-sanitized.json19
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/pure-document-cli-http-tui-linux-aarch64.tar.gzbin0 -> 51844 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-tui-viewport/pure-document-cli-tui-linux-aarch64.tar.gzbin0 -> 34216 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/final-native-window.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/line-width-4096.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/mallinfo.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/no-document-undo.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/no-key-undo.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/no-wrap.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/replace-view.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/same-body.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/same-key.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/settled-final.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/skip-text.json1
-rw-r--r--prototypes/connections/results/2026-09-24-window-memory-analysis/smaps.json1
-rw-r--r--prototypes/connections/results/2026-09-24-work-slot/pure-document-fixed-cli-linux-aarch64.tar.gzbin0 -> 12972 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-work-slot/pure-document-fixed-cli-tui-linux-aarch64.tar.gzbin0 -> 32119 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-work-slot/pure-document-source-cli-linux-aarch64.tar.gzbin0 -> 22784 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-work-slot/pure-document-source-cli-tui-linux-aarch64.tar.gzbin0 -> 51167 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-work-slot/pure-source-preview.tar.gzbin0 -> 334267 bytes
-rw-r--r--prototypes/connections/results/2026-09-24-work-slot/source-package-check.json16
-rw-r--r--prototypes/connections/runtime.c393
-rw-r--r--prototypes/connections/runtime.h147
-rw-r--r--prototypes/connections/server.c645
-rw-r--r--prototypes/connections/source-tui-budget.json12
-rw-r--r--prototypes/connections/store-paged.c529
-rw-r--r--prototypes/connections/store-port.c51
-rw-r--r--prototypes/connections/store-port.h7
-rw-r--r--prototypes/connections/store.c309
-rw-r--r--prototypes/connections/store.h48
-rw-r--r--prototypes/connections/test-async-server-gate.c21
-rw-r--r--prototypes/connections/test-async.c330
-rw-r--r--prototypes/connections/test-fields.c153
-rw-r--r--prototypes/connections/test-flow.c183
-rw-r--r--prototypes/connections/test-paged-store.c270
-rw-r--r--prototypes/connections/test-program.c111
-rw-r--r--prototypes/connections/test-runtime.c356
-rw-r--r--prototypes/connections/test-splice.c190
-rw-r--r--prototypes/connections/tui-budget.json12
-rw-r--r--prototypes/connections/window-budget.json12
616 files changed, 52914 insertions, 0 deletions
diff --git a/prototypes/connections/.gitignore b/prototypes/connections/.gitignore
new file mode 100644
index 0000000..84c048a
--- /dev/null
+++ b/prototypes/connections/.gitignore
@@ -0,0 +1 @@
+/build/
diff --git a/prototypes/connections/Makefile b/prototypes/connections/Makefile
new file mode 100644
index 0000000..502d359
--- /dev/null
+++ b/prototypes/connections/Makefile
@@ -0,0 +1,251 @@
+CC ?= cc
+CFLAGS ?= -O2 -g
+CFLAGS += -std=c17 -Wall -Wextra -Wpedantic -Werror
+BUILD ?= build
+
+.PHONY: all core async-core editor fixed-editor fixed-server fixed-tui source-tui compiler mirror window server async-server document-peer document-server check check-policy check-policy-peer check-portable check-portable-tui check-portable-peer check-native-checkpoint check-mirror check-core check-async check-async-server check-async-service-scale check-profile check-fixed-profile check-fixed-server check-service-scale check-tui-profile check-source-tui-profile check-tui check-source-tui check-release check-micro-memory check-hybrid check-flat-export check-copy-range check-peer-profile check-document-server-profile check-window-profile check-document-peer check-document-server FORCE
+CORE = runtime.c
+STORE ?= store.c
+FIXED_PROGRAM ?= examples/editor.pure
+HOST = $(STORE) store-port.c evaluate.c
+HEADERS = runtime.h program.h store.h store-port.h flow.h result.h
+all: core fixed-editor
+core: $(BUILD)/libpure-execution.a
+async-core: $(BUILD)/libpure-execution-async.a
+editor: $(BUILD)/pure-edit
+fixed-editor: $(BUILD)/pure-edit-fixed
+fixed-server: $(BUILD)/pure-connections-fixed
+fixed-tui: $(BUILD)/pure-edit-tui-fixed
+source-tui: $(BUILD)/pure-edit-tui
+compiler: $(BUILD)/pure-compile
+mirror: $(BUILD)/pure-mirror
+window: $(BUILD)/pure-edit-window
+server: $(BUILD)/pure-connections
+async-server: $(BUILD)/pure-connections-async
+document-peer: $(BUILD)/pure-document-peer
+document-server: $(BUILD)/pure-document-server
+
+$(BUILD):
+ mkdir -p $@
+
+$(BUILD)/pure-connections: server.c $(HOST) flow.c program.c $(CORE) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_RUNTIME_METRICS server.c $(HOST) flow.c program.c $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/pure-connections-async: server.c $(HOST) flow.c program.c $(CORE) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_RUNTIME_METRICS -DPURE_ASYNC_EFFECTS -DPURE_HTTP_ASYNC server.c $(HOST) flow.c program.c $(CORE) $(LDFLAGS) -pthread $(LDLIBS) -o $@
+
+$(BUILD)/pure-connections-async-gated: server.c $(HOST) flow.c program.c $(CORE) test-async-server-gate.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_RUNTIME_METRICS -DPURE_ASYNC_EFFECTS -DPURE_HTTP_ASYNC -DPURE_STORE_TEST server.c $(HOST) flow.c program.c $(CORE) test-async-server-gate.c $(LDFLAGS) -pthread $(LDLIBS) -o $@
+
+$(BUILD)/pure-connections-fixed: server.c $(HOST) flow.c $(CORE) $(HEADERS) $(BUILD)/embedded-plan.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_RUNTIME_METRICS -DPURE_EMBEDDED_PROGRAM -I$(BUILD) server.c $(HOST) flow.c $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/pure-edit: edit.c $(HOST) program.c $(CORE) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) edit.c $(HOST) program.c $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/pure-compile: compile-program.c program.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) compile-program.c program.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/embedded-plan.h: FORCE $(FIXED_PROGRAM) $(BUILD)/pure-compile
+ $(BUILD)/pure-compile $(FIXED_PROGRAM) $@
+
+$(BUILD)/pure-edit-fixed: edit.c $(HOST) $(CORE) $(HEADERS) $(BUILD)/embedded-plan.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_EMBEDDED_PROGRAM -I$(BUILD) edit.c $(HOST) $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/storage-plan.h: FORCE examples/storage.pure $(BUILD)/pure-compile
+ $(BUILD)/pure-compile examples/storage.pure $@
+
+$(BUILD)/pure-mirror: mirror.c $(HOST) $(CORE) $(HEADERS) $(BUILD)/storage-plan.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -I$(BUILD) mirror.c $(HOST) $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/pure-edit-tui-fixed: edit-tui.c $(HOST) $(CORE) $(HEADERS) $(BUILD)/embedded-plan.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_EMBEDDED_PROGRAM -I$(BUILD) edit-tui.c $(HOST) $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/pure-edit-tui: edit-tui.c $(HOST) $(CORE) program.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) edit-tui.c $(HOST) $(CORE) program.c $(LDFLAGS) $(LDLIBS) -o $@
+
+# TLS/socket code is linked only when a document peer is explicitly selected.
+$(BUILD)/pure-document-peer: document-peer.c ../common/tls-link.c ../common/tls-link.h $(HOST) program.c $(CORE) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) document-peer.c ../common/tls-link.c $(HOST) program.c $(CORE) $(LDFLAGS) -lssl -lcrypto $(LDLIBS) -o $@
+
+$(BUILD)/pure-document-server: document-peer.c ../common/tls-link.c ../common/tls-link.h $(HOST) program.c $(CORE) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_PEER_SERVER_ONLY document-peer.c ../common/tls-link.c $(HOST) program.c $(CORE) $(LDFLAGS) -lssl -lcrypto $(LDLIBS) -o $@
+
+# GTK is selected only for the document window. The core, CLI and server do
+# not need its headers, libraries, display server or runtime dependencies.
+$(BUILD)/pure-edit-window: edit-window.c $(HOST) program.c $(CORE) $(HEADERS) | $(BUILD)
+ pkg-config --atleast-version=4.10 gtk4
+ $(CC) $(CPPFLAGS) $(CFLAGS) $$(pkg-config --cflags gtk4) edit-window.c $(HOST) program.c $(CORE) $(LDFLAGS) $$(pkg-config --libs gtk4) $(LDLIBS) -o $@
+
+$(BUILD)/runtime.o: runtime.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c runtime.c -o $@
+
+$(BUILD)/runtime-async.o: runtime.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_ASYNC_EFFECTS -c runtime.c -o $@
+
+$(BUILD)/evaluate.o: evaluate.c program.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c evaluate.c -o $@
+
+$(BUILD)/libpure-execution.a: $(BUILD)/runtime.o
+ rm -f $@
+ $(AR) rcs $@ $^
+
+$(BUILD)/libpure-execution-async.a: $(BUILD)/runtime-async.o
+ rm -f $@
+ $(AR) rcs $@ $^
+
+$(BUILD)/test-flow: test-flow.c store.c flow.c store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_STORE_TEST test-flow.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-program: test-program.c program.c evaluate.c program.h store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-program.c program.c evaluate.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-fields: test-fields.c program.c evaluate.c program.h store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-fields.c program.c evaluate.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-runtime: test-runtime.c program.c $(CORE) $(HOST) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_RUNTIME_METRICS test-runtime.c program.c $(CORE) $(HOST) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-async: test-async.c program.c $(CORE) $(HOST) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_RUNTIME_METRICS -DPURE_ASYNC_EFFECTS test-async.c program.c $(HOST) $(CORE) $(LDFLAGS) -pthread $(LDLIBS) -o $@
+
+$(BUILD)/test-splice: test-splice.c program.c $(CORE) $(HOST) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_RUNTIME_METRICS -DPURE_STORE_TEST test-splice.c program.c $(CORE) $(HOST) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-paged-store: test-paged-store.c store-paged.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_STORE_TEST test-paged-store.c store-paged.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/core-layout: core-layout.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) core-layout.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/core-layout-async: core-layout.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_ASYNC_EFFECTS core-layout.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/measure-peak-rss: measure-peak-rss.c | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) measure-peak-rss.c $(LDFLAGS) $(LDLIBS) -o $@
+
+# Run on the release build, separately from sanitizer-instrumented objects.
+check-core: core $(BUILD)/core-layout
+ python3 check_core.py --archive $(BUILD)/libpure-execution.a --layout $(BUILD)/core-layout $(if $(CORE_EVIDENCE),--output "$(CORE_EVIDENCE)")
+
+check-async: async-core $(BUILD)/core-layout-async $(BUILD)/test-async
+ python3 check_core.py --archive $(BUILD)/libpure-execution-async.a --layout $(BUILD)/core-layout-async --budget async-core-budget.json $(if $(ASYNC_CORE_EVIDENCE),--output "$(ASYNC_CORE_EVIDENCE)")
+ $(BUILD)/test-async
+
+check-async-server: async-server fixed-editor $(BUILD)/pure-connections-async-gated
+ python3 check_profile.py --build $(BUILD) --budget async-server-budget.json $(if $(ASYNC_SERVER_PROFILE_EVIDENCE),--output "$(ASYNC_SERVER_PROFILE_EVIDENCE)")
+ python3 check_async_server.py --server $(BUILD)/pure-connections-async-gated --editor $(BUILD)/pure-edit-fixed $(if $(ASYNC_SERVER_EVIDENCE),--output "$(ASYNC_SERVER_EVIDENCE)")
+
+# Release-linked default hosts are reviewed separately from the execution core.
+# Do not run this size gate on sanitizer-instrumented binaries.
+check-profile: editor server
+ python3 check_profile.py --build $(BUILD) $(if $(PROFILE_EVIDENCE),--output "$(PROFILE_EVIDENCE)")
+
+check-fixed-profile: fixed-editor fixed-server $(BUILD)/measure-peak-rss
+ python3 check_profile.py --build $(BUILD) --budget fixed-budget.json $(if $(FIXED_PROFILE_EVIDENCE),--output "$(FIXED_PROFILE_EVIDENCE)")
+ python3 check_micro_memory.py --build $(BUILD) --fixed $(if $(FIXED_MEMORY_EVIDENCE),--output "$(FIXED_MEMORY_EVIDENCE)")
+
+check-fixed-server: fixed-editor fixed-server server
+ python3 check_fixed_server.py --build $(BUILD) $(if $(FIXED_SERVER_EVIDENCE),--output "$(FIXED_SERVER_EVIDENCE)")
+
+check-service-scale: fixed-editor fixed-server editor server
+ python3 check_service_scale.py --build $(BUILD) $(if $(SERVICE_SCALE_EVIDENCE),--output "$(SERVICE_SCALE_EVIDENCE)")
+
+check-async-service-scale: fixed-editor fixed-server editor server async-server
+ python3 check_service_scale.py --build $(BUILD) --async-source $(if $(SERVICE_SCALE_EVIDENCE),--output "$(SERVICE_SCALE_EVIDENCE)")
+
+check-tui-profile: fixed-tui
+ python3 check_profile.py --build $(BUILD) --budget tui-budget.json $(if $(TUI_PROFILE_EVIDENCE),--output "$(TUI_PROFILE_EVIDENCE)")
+
+check-source-tui-profile: source-tui
+ python3 check_profile.py --build $(BUILD) --budget source-tui-budget.json $(if $(TUI_PROFILE_EVIDENCE),--output "$(TUI_PROFILE_EVIDENCE)")
+
+check-tui: fixed-editor check-tui-profile
+ python3 check_tui.py --build $(BUILD) $(if $(TUI_EVIDENCE),--output "$(TUI_EVIDENCE)")
+
+check-source-tui: editor fixed-editor check-source-tui-profile
+ python3 check_tui.py --build $(BUILD) --source $(if $(TUI_EVIDENCE),--output "$(TUI_EVIDENCE)")
+
+check-release: check-core check-profile check-fixed-profile check check-policy check-micro-memory
+
+check-micro-memory: editor $(BUILD)/measure-peak-rss
+ python3 check_micro_memory.py --build $(BUILD) $(if $(MEMORY_EVIDENCE),--output "$(MEMORY_EVIDENCE)")
+
+check-hybrid:
+ $(MAKE) BUILD=build/hybrid STORE=store-paged.c check build/hybrid/test-paged-store
+ build/hybrid/test-paged-store
+ python3 check_profile.py --build build/hybrid --budget hybrid-budget.json
+ $(MAKE) BUILD=build/hybrid STORE=store-paged.c check-micro-memory
+ python3 check_small_scan.py --editor build/hybrid/pure-edit $(if $(SMALL_SCAN_EVIDENCE),--output "$(SMALL_SCAN_EVIDENCE)")
+ $(MAKE) check-flat-export
+
+# Selected page format can be exported to the unchanged default store format.
+# This conversion tool and test are outside the runtime and default app builds.
+check-flat-export: fixed-editor
+ $(MAKE) BUILD=build/hybrid STORE=store-paged.c fixed-editor
+ python3 check_flat_export.py --paged-editor build/hybrid/pure-edit-fixed --flat-editor $(BUILD)/pure-edit-fixed $(if $(EXPORT_EVIDENCE),--output "$(EXPORT_EVIDENCE)")
+
+# Real source document -> two same-process domains using pinned mapped input.
+check-mirror: mirror fixed-editor $(BUILD)/measure-peak-rss
+ python3 check_mirror.py --mirror $(BUILD)/pure-mirror --editor $(BUILD)/pure-edit-fixed --rss-helper $(BUILD)/measure-peak-rss $(if $(MIRROR_SCRATCH_PARENT),--scratch-parent "$(MIRROR_SCRATCH_PARENT)") $(if $(MIRROR_EVIDENCE),--output "$(MIRROR_EVIDENCE)")
+
+# Selected Linux-only storage copy experiment; does not change the default build.
+check-copy-range: editor $(BUILD)/measure-peak-rss
+ $(MAKE) BUILD=build/cfr CPPFLAGS="$(CPPFLAGS) -DPURE_STORE_CFR_COPY" check check-profile check-micro-memory check-service-scale
+ python3 check_copy_path.py --baseline $(BUILD)/pure-edit --candidate build/cfr/pure-edit --baseline-helper $(BUILD)/measure-peak-rss --candidate-helper build/cfr/measure-peak-rss $(if $(COPY_RANGE_EVIDENCE),--output "$(COPY_RANGE_EVIDENCE)")
+
+check-peer-profile: document-peer
+ python3 check_profile.py --build $(BUILD) --budget peer-budget.json $(if $(PEER_PROFILE_EVIDENCE),--output "$(PEER_PROFILE_EVIDENCE)")
+
+check-document-server-profile: document-server
+ python3 check_profile.py --build $(BUILD) --budget peer-server-budget.json $(if $(PEER_SERVER_PROFILE_EVIDENCE),--output "$(PEER_SERVER_PROFILE_EVIDENCE)")
+
+check-window-profile: window
+ python3 check_profile.py --build $(BUILD) --budget window-budget.json $(if $(WINDOW_PROFILE_EVIDENCE),--output "$(WINDOW_PROFILE_EVIDENCE)")
+
+check-document-peer: check-peer-profile editor
+ python3 check_document_peer.py --peer $(BUILD)/pure-document-peer --editor $(BUILD)/pure-edit $(if $(PEER_EVIDENCE),--output "$(PEER_EVIDENCE)")
+
+check-document-server: check-document-server-profile document-peer editor
+ python3 check_document_peer.py --peer $(BUILD)/pure-document-peer --server $(BUILD)/pure-document-server --editor $(BUILD)/pure-edit $(if $(PEER_SERVER_EVIDENCE),--output "$(PEER_SERVER_EVIDENCE)")
+
+# Opt-in TLS host checks: same authenticated work and failure scenarios without
+# Linux /proc RSS or GNU binary-size tools. Requires OpenSSL headers and libs.
+check-portable-peer: document-peer document-server editor
+ python3 check_document_peer.py --peer $(BUILD)/pure-document-peer --editor $(BUILD)/pure-edit --portable $(if $(PORTABLE_PEER_EVIDENCE),--output "$(PORTABLE_PEER_EVIDENCE)")
+ python3 check_document_peer.py --peer $(BUILD)/pure-document-peer --server $(BUILD)/pure-document-server --editor $(BUILD)/pure-edit --portable $(if $(PORTABLE_DOCUMENT_SERVER_EVIDENCE),--output "$(PORTABLE_DOCUMENT_SERVER_EVIDENCE)")
+
+check: $(BUILD)/test-flow $(BUILD)/test-program $(BUILD)/test-fields $(BUILD)/test-runtime $(BUILD)/test-splice $(BUILD)/pure-edit $(BUILD)/pure-connections
+ $(BUILD)/test-flow
+ $(BUILD)/test-program
+ $(BUILD)/test-fields
+ python3 check.py --server $(BUILD)/pure-connections --runtime-test $(BUILD)/test-runtime --splice-test $(BUILD)/test-splice --editor $(BUILD)/pure-edit --store-source $(STORE) $(if $(EVIDENCE),--output "$(EVIDENCE)")
+
+check-policy: editor server source-tui
+ $(MAKE) BUILD=$(BUILD)/policy FIXED_PROGRAM=examples/bounded-editor.pure fixed-editor fixed-server fixed-tui
+ python3 check_policy.py --source $(BUILD)/pure-edit --fixed $(BUILD)/policy/pure-edit-fixed --source-server $(BUILD)/pure-connections --fixed-server $(BUILD)/policy/pure-connections-fixed --source-tui $(BUILD)/pure-edit-tui --fixed-tui $(BUILD)/policy/pure-edit-tui-fixed --definition examples/bounded-editor.pure $(if $(POLICY_PEER),--peer $(POLICY_PEER)) $(if $(POLICY_EVIDENCE),--output "$(POLICY_EVIDENCE)")
+
+check-policy-peer: document-peer
+ $(MAKE) BUILD=$(BUILD) POLICY_PEER=$(BUILD)/pure-document-peer check-policy
+
+# Host-neutral C smoke path; the release size/RSS gates above are calibrated
+# only for Linux AArch64 and must not be reported as macOS measurements.
+check-portable: $(BUILD)/test-flow $(BUILD)/test-program $(BUILD)/test-fields $(BUILD)/test-runtime $(BUILD)/test-splice $(BUILD)/test-async $(BUILD)/pure-edit $(BUILD)/pure-connections $(BUILD)/pure-edit-tui-fixed $(BUILD)/pure-edit-tui
+ $(BUILD)/test-flow
+ $(BUILD)/test-program
+ $(BUILD)/test-fields
+ $(BUILD)/test-runtime
+ $(BUILD)/test-splice
+ $(BUILD)/test-async
+
+# Same real PTY/CLI scenarios as the Linux TUI gates, with no /proc RSS claim.
+check-portable-tui: fixed-editor fixed-tui editor source-tui
+ python3 check_tui.py --build $(BUILD) --portable $(if $(PORTABLE_FIXED_TUI_EVIDENCE),--output "$(PORTABLE_FIXED_TUI_EVIDENCE)")
+ python3 check_tui.py --build $(BUILD) --source --portable $(if $(PORTABLE_SOURCE_TUI_EVIDENCE),--output "$(PORTABLE_SOURCE_TUI_EVIDENCE)")
+
+# Host-native behavior plus the same real document workload on both CLI variants.
+# RSS is recorded on macOS and Linux; only check-micro-memory enforces the
+# reviewed Linux AArch64 ceiling.
+check-native-checkpoint: check-portable check-portable-tui fixed-editor $(BUILD)/measure-peak-rss
+ python3 check_micro_memory.py --build $(BUILD) --portable $(if $(PORTABLE_SOURCE_MEMORY_EVIDENCE),--output "$(PORTABLE_SOURCE_MEMORY_EVIDENCE)")
+ python3 check_micro_memory.py --build $(BUILD) --fixed --portable $(if $(PORTABLE_FIXED_MEMORY_EVIDENCE),--output "$(PORTABLE_FIXED_MEMORY_EVIDENCE)")
diff --git a/prototypes/connections/README.md b/prototypes/connections/README.md
new file mode 100644
index 0000000..31b9c27
--- /dev/null
+++ b/prototypes/connections/README.md
@@ -0,0 +1,545 @@
+# Pure: 작성한 연결을 준비해 실행하는 네이티브 경로
+
+기존 Workbench에서 만든 코드·배치를 실제 TCP 요청으로 저장하고 새 실행기에서 복원한다.
+서버는 C17 네이티브 실행 파일이다. SQL·SQLite 의존성을 제거했고, 호출자의 바이트를
+그대로 파일에 기록한다. 저장할 구간과 응답할 구간은 `.pure` 파일로 작성하며 서버 시작 때
+실행 경로를 준비한다. 기존 Node/Wasm CLI는 그대로 사용한다.
+
+이 구현은 저장·전송의 수명을 확인하는 최소 경로다. 객체별 파일이나 전체 교체 방식을
+Pure의 최종 데이터 모델로 정한 것은 아니다. 필드 배치·상수 구간·별칭은 준비 단계에서
+처리하고, 입력 값에 의존하는 구간은 요청 때 계산한다.
+[구현 결과와 한계](../../docs/research/021-field-connections.md).
+
+## 실행 코어의 현재 상태
+
+요청 접수·본문 예산·작업 준비·완료·해제를 `runtime.c`가 관리한다. HTTP는 그 코어의 한
+입력/출력 어댑터다. 다른 실행 영역에 결과를 전달할 때 코어가 원본을 유지하며, 수신 영역의
+효과와 응답 소비가 끝나면 회수한다. `test-runtime.c`는 수명·예산 단위 계약을,
+선택형 `make check-mirror`는 실제 1 MiB 문서가 한 프로세스의 두 저장 영역으로
+전달되는 것을 검사한다. [실제 연결 비용과 한계](../../docs/research/063-real-in-process-routing.md).
+
+`make all`은 파서 없는 고정 정의 CLI와 실행 전용 `build/libpure-execution.a`를 만든다.
+빌드 시 `.pure` 정의를 준비하는 컴파일러도 생성하지만 CLI에는 링크되지 않는다.
+실행 중 소스를 읽는 CLI는 `make editor`, HTTP 호스트는 `make server`로 선택한다.
+아카이브에는 `runtime.c`만
+들어가며 문서 평가기·파서·HTTP·POSIX 저장 구현은 없다. 문서 평가는 선택한
+`store-port.c`에 연결된다. 서버는 소스 파일을 읽으므로 파서를 별도로 포함한다.
+기본 호스트 효과는 동기식이고 작성 문법은 아직 get/put 저장 프로필이다.
+전체 앱 런타임·자체 보안 RPC·스레드 간 안전성·강제 메모리 격리를 구현한 것은 아니다.
+[구현·비용·검증 보고서](../../docs/research/022-execution-core.md),
+[첫 공개 체크포인트](../../CHECKPOINT.md).
+
+인증 문서 피어가 필요한 경우 `make document-peer`는 서버·클라이언트 명령을
+한 실행물에 넣는다. 서버만 배치할 때는 `make document-server`를 선택할 수 있다.
+`make check-document-server`는 서버 전용 코드·의존성 상한과 기존 C/Python TLS
+문서 시나리오를 검사한다. 이 선택 빌드는 기본 코어·CLI에 TLS를 추가하지 않는다.
+루프백의 [직접 서버 비교와 전송 지연 결과](../../docs/research/055-authenticated-peer-transport-cost.md)는
+전체 프로세스 비용과 아직 남은 다중 연결 한계를 함께 기록한다.
+이동 가능한 서버 전용 묶음은 `package_native.py --with-peer-server --output FILE`로
+만들고 `check_package.py FILE`로 검증한다. CLI+TLS 아카이브 전체 상한과
+[이동 후 인증·문서 작업 결과](../../docs/research/056-server-only-document-package.md)를
+별도로 공개한다.
+
+## 필요한 구성만 빌드하기
+
+`make core`, `make fixed-editor`, `make editor`, `make server`로 구성을 각각 선택한다. `make core`에는
+소스 파서·저장소·네트워크·UI가 들어가지 않는다. 영역마다 스레드·소켓·힙을 생성하지 않는다.
+release 빌드의 `make check-core`는 코어 코드 섹션 4,864 B, data/BSS 0 B와 현재 구조체 비용의
+상한·아카이브 의존성을 검사한다. 현재 Linux AArch64의 기본 구성은
+`text` 4,632 B / 영역 120 B / 작업 216 B다. 누적 계수가 필요한 HTTP 호스트와
+테스트는 `PURE_RUNTIME_METRICS`를 선택한다. 이 프로필의 영역은 192 B다.
+코어에서 문서 해석을 분리하기 전의 `text` 5,980 B / 영역 128 B와 구분한다.
+[현재 경계와 전체 앱 비용](../../docs/research/068-opaque-app-core.md)에 기록했다.
+[해제 콜백 재진입 방어 비용](../../docs/research/064-release-callback-reentrancy.md)을
+기본 코어 상한 안에서 검증했다.
+[실제 앱 1,000개 비교](../../docs/research/051-optional-runtime-metrics.md)에서 두 비용을
+분리했다. 전체 앱의 RAM 수치는 아니다. GNU 호환 도구를 사용하는 현재 프로필의 회귀 검사다.
+`make check-profile`은 기본 CLI·HTTP 실행물의 링크된 섹션과 직접 동적 의존성을 검사한다.
+두 검사를 실제 동작·CLI 전체 프로세스 RSS 검사와 함께 실행할 때는 release 빌드에서
+`make check-release`를 사용한다. RSS 검사는 1 B/1 MiB 실제 문서 편집·읽기를
+[현재 장치의 4 MiB 회귀 상한](memory-budget.json)과 비교한다.
+이 검사에는 파서 없는 고정 정의 CLI·HTTP 실행물의 크기·RSS 상한도 포함된다.
+`make check-service-scale`은 같은 문서 앱의 1,024개 객체를 8개 클라이언트가
+생성·읽기·수정·복원하여 두 HTTP 호스트의 결과, 서버 RSS, 버퍼 회수를 확인한다.
+[검사 범위와 결과](../../docs/research/040-document-service-capacity.md).
+`make check-async`는 선택형 비동기 완료 코어와 실제 저장 효과를 검사한다.
+유휴 동기 앱은 `pure_runtime_bind()`로 작업 슬롯을 분리할 수 있다. 진행 중인
+작업·대여가 남으면 분리를 거절하며, 슬롯 재결합에도 티켓 세대는 유지된다.
+[실제 네이티브 앱 1,000개의 메모리 비용](../../docs/research/049-idle-app-work-slots.md).
+기본 코어·CLI·HTTP에는 작업자 스레드나 비동기 완료 코드가 링크되지 않는다.
+선택형 코어 자체는 작업자를 만들지 않으며, 효과를 가져온 호스트가 I/O를 실행하고
+같은 소유 스레드에서 완료해야 한다. 기본 서비스 호스트는 이 경로를 사용하지
+않는다. [계약·비용·한계](../../docs/research/045-owner-thread-async-effects.md).
+`make async-server`는 이 계약을 기존 문서 HTTP 앱에 선택적으로 연결한다.
+`make check-async-server`는 크기 상한과 쓰기가 멈춘 동안 기존 문서 읽기·기한·
+종료를 검사하고, `make check-async-service-scale`은 기존 1,024개 문서 작업을
+같은 소스 정의 앱으로 다시 실행한다. 이 선택 호스트는 읽기 작업자 하나와
+쓰기 작업자 하나를 사용하고, 모든 쓰기는 한 작업자에서 직렬화한다.
+[현재 동작과 비용](../../docs/research/048-immutable-read-write-overlap.md).
+GTK·TLS를 선택하지 않아도 기본 실행물에 섞이면 검사가 실패한다. 예산은
+[`profile-budget.json`](profile-budget.json)에 기록했으며, 호스트·컴파일러가 바뀌면
+측정값을 다시 검토해야 한다. 이 검사만으로 전체 앱 RAM이 작다고 증명하지는 않는다.
+[현재 비용과 제한](../../docs/research/023-document-edits.md).
+
+Linux AArch64의 기본 시험 묶음에는 CLI와 `.pure` 정의만 넣는다. `make check-micro-memory`로
+빌드한 뒤 첫 명령을 실행한다. 전체 교차 검증 묶음은 `make all server document-peer window`
+와 `make check-micro-memory` 뒤에 HTTP·피어·창을 모두 명시적으로 선택한다.
+패키징은 CLI 메모리 상한도 다시 확인한다. 소스 작성 묶음은 디버그 정보를,
+고정 정의 묶음은 실행에 필요 없는 심볼까지 제거하며 빌드 실행물은 그대로 둔다.
+둘 다 정적 실행물이 아니고 매니페스트에 시스템 공유
+라이브러리를 기록한다. `check_package.py`는 묶음을 다른 위치에 풀어 선택된
+경로의 실제 동작을 다시 확인한다.
+고정 정의 묶음은 선택한 CLI·HTTP·TUI 조합의 압축 아카이브 전체 크기 상한도
+[`fixed-package-budget.json`](fixed-package-budget.json)으로 검사한다. 초과하면 패키지를
+만들지 않는다. 이 값은 libc·터미널·저장 파일을 포함한 실행 메모리 값은 아니다.
+[현재 터미널 편집기](../../docs/research/044-terminal-viewport-cost.md)는 여러 행·탭 문서의
+재열기를 처리하며, 1 MiB 화면의 반복 입력은 문서 전체를 매번 스캔하지 않는다.
+[문서 이름 접두어 탐색](../../docs/research/050-bounded-document-prefix-find.md)은 이미 정렬된
+목록을 사용하며, 목록을 연 상태에서 이름을 입력하고 Enter로 연다. Backspace는
+접두어를 줄이고 화살표는 검색어를 지운 뒤 목록을 이동한다.
+
+```sh
+python3 prototypes/connections/package_native.py \
+ --output dist/pure-document-micro-linux-aarch64.tar.gz
+python3 prototypes/connections/check_package.py \
+ dist/pure-document-micro-linux-aarch64.tar.gz
+
+python3 prototypes/connections/package_native.py \
+ --with-http --with-peer --with-window \
+ --output dist/pure-document-authoring-linux-aarch64.tar.gz
+python3 prototypes/connections/check_package.py \
+ dist/pure-document-authoring-linux-aarch64.tar.gz
+```
+
+필요한 호스트만 선택할 수도 있다. 예를 들어 `--with-window`만 주면 HTTP·TLS 없이
+CLI와 GTK 창만 포함하며, 창의 외부 변경·충돌은 CLI를 통해 검증한다.
+
+[기본·선택 묶음, 메모리 비용과 한계](../../docs/research/032-micro-native-authoring-boundary.md).
+
+동일한 문서 인터페이스에 인라인/16 KiB 페이지 혼합 저장소를 **선택형 연구 경로**로 붙여볼 수 있다.
+작은 기존 `PUREB001` 값은 그대로 읽지만, 큰 값을 `PUREP001`로 바꾼 뒤에는 기본 저장기로
+직접 열 수 없다. 따라서 실험에 별도 `--store` 디렉터리를 쓴다. 아래 내보내기
+명령은 새 기본 형식 디렉터리를 만들어 본문·리비전을 보존하며, 기존 디렉터리를
+제자리에서 바꾸지 않는다. 기본 저장소를 교체하는 명령이 아니다.
+
+```sh
+make -C prototypes/connections check-hybrid
+printf 'hello Pure\n' > /tmp/pure-hybrid-insert.txt
+prototypes/connections/build/hybrid/pure-edit \
+ --program prototypes/connections/examples/editor.pure \
+ --store /tmp/pure-hybrid-documents edit note 0 0 0 /tmp/pure-hybrid-insert.txt
+prototypes/connections/build/hybrid/pure-edit \
+ --program prototypes/connections/examples/editor.pure \
+ --store /tmp/pure-hybrid-documents show note
+python3 prototypes/connections/package_native.py \
+ --build prototypes/connections/build/hybrid --hybrid-storage \
+ --output dist/pure-document-hybrid-micro-linux-aarch64.tar.gz
+make -C prototypes/connections check-flat-export
+python3 prototypes/connections/export_flat_store.py \
+ --source /tmp/pure-hybrid-documents --destination /tmp/pure-flat-documents \
+ --paged-editor prototypes/connections/build/hybrid/pure-edit-fixed \
+ --flat-editor prototypes/connections/build/pure-edit-fixed
+```
+
+[실제 큰·작은 문서 쓰기량과 전체 제한](../../docs/research/034-hybrid-document-storage.md),
+[기본 형식으로 내보내는 검증](../../docs/research/062-paged-store-rollback.md).
+
+같은 `.pure` 문서 편집기를 선택형 페이지 저장소와 함께 터미널에서 사용하려면
+Linux의 16 KiB OS 페이지 환경에서 새 저장 디렉터리를 지정한다. CLI와 TUI를
+함께 담은 [선택형 묶음](results/2026-09-24-native-save/pure-document-hybrid-cli-tui-linux-aarch64.tar.gz)은
+다음 빌드로 만들며, 기본 `make all`과 기본 저장 형식은 유지된다.
+
+```sh
+make -C prototypes/connections BUILD=build/hybrid STORE=store-paged.c editor source-tui
+python3 prototypes/connections/package_native.py \
+ --build prototypes/connections/build/hybrid --hybrid-storage --with-tui \
+ --output dist/pure-document-hybrid-cli-tui-linux-aarch64.tar.gz
+python3 prototypes/connections/check_package.py \
+ dist/pure-document-hybrid-cli-tui-linux-aarch64.tar.gz
+```
+
+[실제 Ctrl+S 완료 시간·코드·RSS 비용](../../docs/research/065-native-save-latency.md)을
+함께 검토해야 한다. 큰 문서의 `PUREP001` 형식은 기본 저장기가 직접 열 수 없다.
+
+기본 `PUREB001` 형식을 유지하며 큰 수정의 사용자 공간 복사 호출을 줄이는
+Linux 전용 선택형 실험은 `make -C prototypes/connections check-copy-range`로
+검사한다. `strace`·`findmnt`와 GNU 크기 도구가 필요하며, 기본 `make editor`에는
+이 경로가 들어가지 않는다. [같은 1 MiB 문서의 시스템 호출·전체 RSS·코드 비용과
+지원 범위](../../docs/research/059-immutable-file-copy-path.md)를 분리해 공개한다.
+
+## 네이티브 CLI로 문서 일부 바꾸기
+
+저장소 루트에서 실행한다. 입력 파일에 삽입할 실제 내용만 둔다.
+
+```sh
+make -C prototypes/connections editor
+printf 'hello Pure\n' > /tmp/pure-insert.txt
+prototypes/connections/build/pure-edit --program prototypes/connections/examples/editor.pure --store prototypes/connections/build/edited-objects edit note 0 0 0 /tmp/pure-insert.txt
+printf 'world' > /tmp/pure-insert.txt
+prototypes/connections/build/pure-edit --program prototypes/connections/examples/editor.pure --store prototypes/connections/build/edited-objects edit note 1 6 4 /tmp/pure-insert.txt
+prototypes/connections/build/pure-edit --program prototypes/connections/examples/editor.pure --store prototypes/connections/build/edited-objects show note
+```
+
+새 저장소에서 마지막 출력은 `hello world`와 줄바꿈이다. `edit`의 숫자는 예상 버전·시작 바이트·
+삭제 바이트 수다. 성공 시 JSON 버전을 출력하며, `show`는 stdout에 원문을, stderr에 버전을
+출력한다. 버전 충돌의 종료 코드는 3, 다른 오류는 2다. 변경이 없더라도 성공한 효과는 버전을
+증가시킨다. UTF-8 문자소 위치는 호출자가 바이트 범위로 변환해야 한다.
+
+편의 명령은 준비된 두 숫자 필드와 뒤따르는 삽입 바이트를 채운다. 다른 입력 구성은
+`apply KEY REVISION INPUT_FILE`로 실행한다. `--budget BYTES`를 명령 앞에 지정하면 입력/결과의
+본문 크레딧을 제한한다. 저장소가 파일을 다시 쓰는 4 KiB 스택 버퍼·커널 비용은 별도다.
+서버에 같은 `editor.pure`·저장 경로를 지정하면 외부 HTTP 입력도 같은 효과를 실행한다.
+이 CLI는 네이티브 자동화 경로다. 문서 창은 아래의 선택 빌드다.
+
+## 인증된 문서 피어
+
+`make document-peer`는 같은 `editor.pure`·저장소·실행 코어를 사용하면서 TLS 1.3
+상호 인증과 `pure-doc/1` 자체 이진 형식을 선택 빌드한다. 기본 `make all`에는
+OpenSSL이 들어가지 않는다. 준비된 CA와 서버·클라이언트 인증서가 필요하며,
+서버 인증서의 DNS SAN은 `localhost`, 클라이언트 인증서의 DNS SAN은
+아래 예시의 `pure-client`와 일치해야 한다.
+
+```sh
+make -C prototypes/connections document-peer
+prototypes/connections/build/pure-document-peer serve 127.0.0.1 9443 \
+ prototypes/connections/examples/editor.pure /tmp/pure-documents \
+ /path/to/ca.pem /path/to/server.pem /path/to/server.key pure-client
+prototypes/connections/build/pure-document-peer call 127.0.0.1 9443 localhost \
+ prototypes/connections/examples/editor.pure /path/to/ca.pem \
+ /path/to/client.pem /path/to/client.key show note
+```
+
+`call`은 `show KEY`, `edit KEY REVISION OFFSET REMOVE INSERT_FILE`,
+`apply KEY REVISION INPUT_FILE`을 받는다. 읽기는 원문을 stdout에 보낸다.
+편집은 결과 본문을 소비하지 않으므로 논리적 결과 길이만 받고 본문 전송은 생략한다.
+서버는 지속 세션을 처리하지만 예제 C 명령은 호출마다 연결한다. 인증서를 자동 생성해
+실제 C·Python 클라이언트, 1 MiB 문서, 실패·재시작을 검사하려면
+`make -C prototypes/connections check-document-peer`를 실행한다. 이 대상은 선택형
+실행물의 코드·직접 의존성 [예산](peer-budget.json)도 검사한다.
+[형식·비용·한계](../../docs/research/030-authenticated-document-peer.md).
+
+## 네이티브 문서 창
+
+Linux에서 GTK 4.10 이상 개발 헤더·라이브러리와 `pkg-config`가 있으면 같은
+[`editor.pure`](examples/editor.pure)를 실제 텍스트 창으로 실행할 수 있다. GTK는 이
+선택 빌드에만 들어가며 `make all`이나 코어·CLI·서버의 의존성이 아니다.
+
+```sh
+make -C prototypes/connections window
+prototypes/connections/build/pure-edit-window \
+ --program prototypes/connections/examples/editor.pure \
+ --store /tmp/pure-documents note
+```
+
+문서를 편집한 뒤 **Save** 또는 Ctrl+S를 누른다. **Definition** 버튼 또는
+Ctrl+Shift+D로 같은 `.pure` 소스를 편집하고 **Apply & save** 또는 Ctrl+Shift+S로
+현재 창에 적용한다. 잘못된 정의, 다른 실행기의 소스 변경, 저장 실패는 초안과 기존
+실행 계획을 보존한다. 다른 실행기는 재시작한 뒤 저장된 정의를 읽는다.
+창 아래의 문서 키 입력과 **Open** 또는 Ctrl+O로 다른 문서를 연다. 없는 키는 새
+빈 문서로 열고, 미저장 문서·정의 초안이 있거나 키·본문이 유효하지 않으면
+현재 문서와 버전을 유지한다. 목록·검색 기능은 아직 없다.
+변경한 바이트 구간만 작성된 splice 입력에
+넣고, 저장소는 이전 버전이 일치할 때만 공개한다. CLI·HTTP 서버도 같은 프로그램과 저장
+경로를 쓰므로 다른 실행기가 먼저 저장하면 창은 초안을 유지하며 충돌을 보여준다. Reload는
+미저장 변경을 보호하고 Discard & reload만 명시적으로 버린다. 닫기·Ctrl+W도 미저장
+초안을 확인한다. 창은 UTF-8 텍스트만 열며 이진 데이터는 CLI로 다룬다.
+
+실제 창·CLI·HTTP 교차 검증, 정의 적용·실패 복구, 1 MiB 문서 수정과 전체 메모리 비용은
+[032 보고서](../../docs/research/032-micro-native-authoring-boundary.md)에 있다. 화면 없이
+같은 시나리오를 재현하려면 Xvfb·xdotool·xclip을 설치하고 다음을 실행한다.
+
+```sh
+make -C prototypes/connections window editor server
+xvfb-run -a -s '-screen 0 1280x800x24' \
+ python3 prototypes/connections/check_window.py
+```
+
+## 작은 네이티브 터미널 편집기
+
+빌드 시 준비한 같은 문서 앱을 GTK 없이 터미널에서 편집하려면 `fixed-tui`를
+선택한다. Ctrl+S 저장, Ctrl+O 다른 키 열기, Ctrl+R 다시 읽기, Ctrl+Q 종료다.
+미저장 초안을 버리려면 다시 읽기·종료 명령을 두 번 입력해야 한다. 이 실행물은
+`.pure` 정의를 실행 중 다시 작성하지 않는다.
+
+```sh
+make -C prototypes/connections fixed-tui
+prototypes/connections/build/pure-edit-tui-fixed --store /tmp/pure-documents note
+make -C prototypes/connections check-tui
+python3 prototypes/connections/package_native.py --fixed --with-tui \
+ --output dist/pure-document-cli-tui-linux-aarch64.tar.gz
+```
+
+실제 PTY 조작·1 MiB 편집·프로세스 메모리·패키지의 범위는
+[042 보고서](../../docs/research/042-micro-native-terminal-editor.md)에 있다.
+
+실행 시 `.pure` 정의를 읽는 TUI가 필요하면 `source-tui`를 선택한다. 기존 고정 TUI와
+달리 파서가 선택한 실행물에 포함된다. 정의를 고친 뒤 새 세션을 열어야 적용되며,
+편집 중인 문서 상태를 묵시적으로 변환하지 않는다. 기본 코어와 고정 TUI에는 영향이 없다.
+
+```sh
+make -C prototypes/connections source-tui
+prototypes/connections/build/pure-edit-tui --program \
+ prototypes/connections/examples/editor.pure --store /tmp/pure-documents note
+make -C prototypes/connections check-source-tui
+python3 prototypes/connections/package_native.py --with-tui \
+ --output dist/pure-document-source-cli-tui-linux-aarch64.tar.gz
+```
+
+구체적인 지원 범위와 전체 비용은 [소스 TUI 검증](../../docs/research/053-source-loaded-native-terminal-editor.md)에 기록한다.
+
+## 실행
+
+POSIX 환경의 C17 컴파일러와 make가 필요하다. 검증 환경은 Linux AArch64다.
+저장소 루트에서 실행한다.
+
+```sh
+make -C prototypes/connections server
+prototypes/connections/build/pure-connections --program prototypes/connections/examples/storage.pure --store prototypes/connections/build/objects --port 8767
+```
+
+`--store`는 디렉터리다. 기존 SQLite 파일 등 일반 파일을 지정하면 거절하며 덮어쓰거나
+변환하지 않는다. 자동 마이그레이션은 제공하지 않는다.
+`--program`은 필수다. 파일 수정은 다음 서버 시작에 반영되며 실행 중 교체는 지원하지 않는다.
+
+다른 터미널에서 기존 작업물을 연다. Node가 필요하다.
+
+```sh
+node prototypes/workbench/cli.mjs prototypes/workbench/examples/direct.pure
+```
+
+CLI에서 실행할 예:
+
+```text
+point drag down 90 170
+point drag move 360 220
+point drag up 360 220
+connect http://127.0.0.1:8767 my_work
+push 0
+quit
+```
+
+빈 CLI를 다시 실행하고 `connect http://127.0.0.1:8767 my_work`, `pull`, `show`를 입력하면
+저장한 배치가 복원된다. 이후 변경은 `push`로 저장한다. `push 0`은 새 이름을 만들 때만 사용한다.
+서버를 재시작해도 같은 저장 디렉터리를 지정하면 내용을 읽을 수 있다. 다른 실행기가 먼저
+갱신했다면 412 충돌로 거절하고 로컬 배치를 유지한다. `pull`은 로컬 배치를 원격 내용으로
+교체하므로, 보존할 작업은 먼저 `save-project PATH`로 저장한다.
+
+## 필드로 문서 선택·저장하기
+
+[selection.pure](examples/selection.pure)는 선택 시작·길이와 문서를 입력받아 선택한 내용만
+저장하고 응답한다. 필드의 바이트 위치를 연산마다 직접 계산하지 않는다.
+
+```text
+layout Selection {
+ start: u32le;
+ count: u32le;
+ document: bytes;
+}
+
+on put {
+ let input = view(Selection, request.body);
+ let selected = range(input.document, input.start, input.count);
+ let saved = store.write(request.key, request.revision, selected);
+ reply(saved, selected);
+}
+```
+
+예제 파일에는 저장한 내용을 조회하는 get도 있다. 별도 저장 디렉터리로 실행한다.
+
+```sh
+prototypes/connections/build/pure-connections --program prototypes/connections/examples/selection.pure --store prototypes/connections/build/selections --port 8768
+```
+
+다른 터미널에서 UTF-8 텍스트 파일의 선택 구간을 저장한다. `--start`·`--end`는 0부터 시작하는
+유니코드 코드 포인트 위치이며 끝은 포함하지 않는다. 바이트 위치 변환과 입력 인코딩은
+예제 Python 클라이언트가 맡는다. 사용자에게 보이는 글자 덩어리(grapheme) 단위는 아니다.
+
+```sh
+python3 prototypes/connections/examples/select-text.py /path/to/document.txt --key excerpt --start 0 --end 5 --url http://127.0.0.1:8768
+```
+
+성공하면 저장 버전과 선택 내용이 출력된다. 이후 갱신에는 `--revision 1`처럼 현재 버전을
+지정한다. 서버의 숫자 필드는 바이트 단위다. 예제 클라이언트는 UTF-8 문자 경계에 맞추지만
+서버의 `bytes` 필드 자체가 텍스트 인코딩을 검증하는 것은 아니다. 클라이언트는 Python이며
+필드 해석·범위 계산·저장·응답을 하는 서버는 네이티브다.
+
+`layout`은 선택한 입출력 경계의 배치 선언이다. 패딩 없이 선언 순서로 필드를 배치하며,
+`u32le`, `bytes[N]`, 마지막 가변 `bytes`를 지원한다. 고정 필드만 있는 선언은 접두부를 읽는다.
+다른 입력·저장·RAM 표현을 이 형식으로 바꾸도록 강제하지 않는다. 송신자와 수신자의 선언이
+맞아야 하며 자동 형식 감지·버전 변환은 없다. 예제는 두 u32 뒤에 원본 UTF-8 바이트를 보낸다.
+
+필드 이름과 타입은 준비 단계에서 접근 위치로 바뀐다. 요청별 이름 검색이나 레코드 객체
+할당은 없다. 이 예제에는 요청 시 계산할 범위가 하나 남고 저장·응답이 그 결과를 함께 참조한다.
+입력 헤더가 잘렸거나 범위가 틀리면 저장 전에 실패한다.
+[필드 연결 계약](../../docs/design/005-field-connections.md).
+
+## 상수 구간 작성과 준비 결과 확인
+
+[storage.pure](examples/storage.pure)는 전체 작업물을 저장·복원하는 기존 동작이다.
+[excerpt.pure](examples/excerpt.pure)는 저장된 본문의 일부만 응답한다. 다음 get 정의에서
+원본은 최소 80 B여야 하며 실제 응답은 오프셋 32부터 16 B다.
+
+```text
+on get {
+ let object = store.read(request.key);
+ let window = range(object.body, 16, 64);
+ let excerpt = range(window, 16, 16);
+ reply(object, excerpt);
+}
+```
+
+준비 결과는 저장소·소켓을 만들지 않고 확인할 수 있다. 서버의 `--program`에 같은 파일을
+지정하면 해당 경로로 실행한다. 부분 응답 예제는 전체 JSON을 요구하는 Workbench `pull`용이 아니다.
+
+```sh
+prototypes/connections/build/pure-connections --check-program prototypes/connections/examples/excerpt.pure
+```
+
+`on put`에서는 저장할 부분을 고르고 같은 입력을 응답에도 연결할 수 있다.
+해제·복사 코드를 따로 쓰지 않아도 원본 수신 버퍼를 전송 완료까지 유지한다.
+
+```text
+on put {
+ let window = range(request.body, 2, 10);
+ let value = range(window, 3, 4);
+ let saved = store.write(request.key, request.revision, value);
+ reply(saved, value);
+}
+```
+
+두 핸들러가 모두 필요하고 각각 저장 효과는 한 번이다. `range`는 정확한 범위를 검사한다.
+사용하지 않은 구간의 실패도 보존하며, 쓰기의 모든 구간 정의는 저장 호출보다 앞에 둔다.
+작성 오류는 저장소 초기화 전에 거절한다. 소스는 16 KiB, 핸들러당 정의는 32개까지다.
+배치 선언은 4개, 선언당 필드는 16개, 입력 값에 의존하는 구간 계산은 8단계까지다.
+이 동적 범위는 PUT 입력에 한정하며 GET의 숫자 필드 값으로 결정하는 범위는 시작 때 거절한다.
+GET의 이름 기반 고정 필드·가변 꼬리 구간은 지원한다. 숫자/화면 DSL과 파서는 아직 별개다.
+조건 분기·반복·여러 외부 효과·일반 산술은 이번 프로파일에 없다.
+[작성 계약](../../docs/design/004-prepared-connections.md).
+
+실제 문서 효과에는 선택형 최종 크기 정책을 쓸 수 있다.
+[`bounded-editor.pure`](examples/bounded-editor.pure)의
+`store.splice(request.key, request.revision, edit.start, edit.remove, edit.insert, 8)`은
+수정 후 문서가 8 B를 넘으면 `limit`을 돌려준다. 현재 크기·제거 범위·삽입 길이는
+쓰기 잠금 안에서 같은 버전으로 계산한다. 상한은 작성자가 준비한 상수이며 요청 본문이
+정책을 바꿀 수 없다. 기본 `editor.pure`는 기존 객체 상한을 사용한다.
+`make check-policy`는 소스·고정 CLI/HTTP/TUI의 허용·거절·리비전·초안 보존을,
+`make check-policy-peer`는 선택형 인증 피어까지 같은 정의로 검사한다.
+이 기능은 문서 어댑터와 저장소에만 있고 4,632 B 기본 코어와 작업 슬롯은 늘리지 않는다.
+일반 숫자 규칙 언어가 완성됐다는 뜻은 아니다.
+
+`--check-program`의 `steps`가 비면 구간 연산은 준비 단계에서 끝난다. `write_step`·`reply_step`이
+0이면 정적인 범위 설명을 쓰고, 양수이면 `steps`의 해당 1-based 결과를 사용한다.
+`to_end`는 offset부터 원본 끝까지를 뜻한다. `runtime_view_steps`는 준비된 동적 단계 수이며
+실행 속도나 CPU 명령 수 측정값이 아니다. 오류가 나면 뒤 단계와 저장 효과는 실행하지 않는다.
+
+## 연결과 소유권
+
+| 경로 | 데이터와 완료의 의미 |
+|---|---|
+| 수신 → 저장 | 본문 크기만큼 한도를 예약하고 수신한다. 작성한 구간을 쓰기 호출에 전달한다. 응답도 입력을 사용하면 전송 종료까지 원본을 유지하며, 아니면 쓰기 호출 종료 후 반납한다. |
+| 저장 → 공개 | 쓰기 잠금 안에서 예상 revision을 확인한다. 새 파일에 메타데이터와 본문을 기록·fsync하고 rename으로 공개한다. |
+| 공개 → 응답 | 디렉터리 fsync까지 성공해야 저장 성공으로 응답한다. 공개 후 fsync 실패는 `durability_unknown`이며 롤백으로 표현하지 않는다. |
+| 조회 → 전송 | 중간 구간들의 길이 조건과 최종 범위를 같은 파일 버전에서 검사한다. 응답에 필요한 부분만 읽기 전용으로 매핑한다. 별도의 응답 본문 배열을 만들지 않는다. |
+| 부분 전송 → 회수 | 헤더·본문의 전송 위치만 전진시킨다. 마지막 바이트를 OS에 넘겼거나 전송이 중단되면 매핑을 해제한다. 상대 앱의 수신 확인은 별개다. |
+| 복원 → 상태 공개 | 클라이언트가 UTF-8·기존 작업물 형식·상태를 검증한 뒤 복원한다. 실패하면 로컬 상태와 기억한 원격 revision을 유지한다. |
+
+저장된 버전은 제자리에서 수정하지 않는다. 새 파일로 교체하므로 기존 매핑은 전송이 끝날
+때까지 이전 버전을 참조한다. 이는 불변 파일 운용 규칙에 의한 보장이다. 외부 프로그램이
+파일을 직접 수정·잘라내는 경우까지 `mmap`이 스냅샷을 보장하는 것은 아니다.
+
+저장 C API의 `pure_store_select`는 준비된 구간과 최소 원본 길이를 받아 필요한 부분만 매핑한다.
+기본 `storage.pure`와 Workbench 복원은 전체 작업물을 사용한다. HTTP Range나 저장 파일의
+제자리 부분 갱신은 구현한 것이 아니다. 본문 없는 응답도 존재·파일 형식 검사는 수행한다.
+
+파일은 식별자·버전·길이의 24 B 헤더 뒤에 원본 본문을 둔다. 테이블·행·쿼리 계획은 없다.
+이 헤더는 공개·복원을 위한 프로토타입 메타데이터이며 새 범용 문서·미디어 형식이 아니다.
+Workbench JSON의 의미 검증은 클라이언트가 맡는다. 이 JSON이나 파일 배치를 Pure의 RAM
+표현으로 강제하지 않는다. 현재 작성 가능한 연결은 등록된 읽기·쓰기·응답에 한정되며
+[모듈 계약 초안](../../docs/design/003-module-contract.md) 전체의 구현은 아니다.
+
+`GET /objects/NAME`, `PUT /objects/NAME`의 제한된 HTTP/1.1 요청 경로다.
+이름은 영문·숫자·`_`·`-` 1~64자다. 생성은 `If-None-Match: *`, 갱신은 `If-Match: "revision"`을
+요구한다. 성공한 조회·저장은 `ETag: "revision"`을 반환한다. revision은 64비트 양수이며
+클라이언트에서도 문자열로 유지한다. 404 없음, 412 충돌, 413 크기/버전 한도,
+503 예산 부족/쓰기 잠금, 500 저장 오류를 구분한다. 500의 `X-Pure-Error: durability_unknown`은
+새 내용이 이미 공개됐지만 영속화 확인이 실패했다는 뜻이다. 재조회는 현재 내용을 확인할
+수 있을 뿐 전원 장애 내구성을 증명하지 않는다. 응답 유실도 저장 취소를 뜻하지 않는다.
+요청마다 연결을 닫고 Content-Length만 지원한다. 범용 HTTP/RPC 서버는 아니다.
+
+HTTP를 Pure 간 기본 통신 모델로 확정한 것은 아니다.
+[자체 통신 형식 설계](../../docs/design/006-native-protocol.md)는 작성된 연결에서 바이너리
+형식을 준비하고 보안 전송을 별도로 선택하는 방향이다. 같은 get/put 효과를 실행하는
+[선택형 인증 문서 피어](../../docs/research/030-authenticated-document-peer.md)가 별도로 있다.
+이 평문·요청당 연결 종료 HTTP 경로로 QUIC과 성능을 비교하지 않는다.
+
+## 한도와 남은 비용
+
+- 이 절의 HTTP 서버는 `127.0.0.1`에만 바인드하며 인증·TLS가 없다. 인증된 선택형
+ 문서 피어는 별도 실행물이고 인터넷 공개 배포는 검증하지 않았다.
+- 동시 연결은 8개, 헤더는 연결당 4 KiB, 객체는 Workbench 파일 상한인 1,449,984 B까지다.
+- 현재 준비 구조체는 검증 환경에서 프로그램당 648 B다. 동적 구간 8개를 위한 공간도
+ 고정 예약한다. 이름·필드 표는 준비 후 유지하지 않지만 전체 컴파일·실행 메모리의 상한을 뜻하지 않는다.
+- `--budget` 기본값은 4 MiB다. 수신 본문 할당과 전송 중 참조하는 본문 길이를 합해 접수한다.
+ 이는 전체 RSS·매핑 페이지·페이지 캐시·디스크 사용량의 상한이 아니다. 매핑 정렬·페이지
+ 단위 비용, OS 소켓 버퍼, 클라이언트 JSON·문자열·응답 버퍼도 별도다.
+ 입력의 일부만 응답해도 원본 수신 할당 전체를 붙잡으므로 해당 예산을 전부 유지한다.
+- 헤더와 함께 받은 본문 접두부는 한 번 복사하며 `ingress_prefix_copy_bytes`에 기록한다.
+ `borrowed_output_bytes`는 참조한 구간의 누적 길이다. 절약한 RAM의 측정값이 아니다.
+ 커널의 파일 쓰기·소켓 전송, 페이지 폴트, 클라이언트의 직렬화 비용은 남는다.
+- `--timeout-ms` 기본값은 접속부터 10초다. 느린 송수신자는 기한 뒤 종료한다. 파일 작업은
+ 동기 실행하므로 디스크 호출 중에는 기한을 강제로 집행하거나 취소하지 못한다.
+- 매핑을 유지하면 이전 파일의 저장 공간도 남을 수 있다. 작은 범위 참조도 해당 파일 버전의
+ 디스크 수명을 연장한다. 본문 예산만으로 장기 운용의 디스크 사용량을 보장하지 않는다.
+- 쓰기는 디렉터리별 잠금 하나로 직렬화한다. C API 제어 호출은 단일 스레드를 전제로 하며,
+ 이 잠금 규칙을 따르는 여러 프로세스의 충돌을 처리한다. 다중 객체 트랜잭션은 없다.
+- 공개 전 프로세스가 종료되면 `.pending-*` 파일이 남을 수 있다. 읽기는 이를 무시하며
+ 자동 정리·디스크 복구 정책은 아직 없다. 본문 손상 검출용 체크섬도 없다.
+- macOS 실행, 실제 전원 장애·디스크 고장은 검증하지 않았다. 파일을 이 어댑터 밖에서
+ 제자리 수정하지 않는 로컬 저장소를 전제로 한다.
+
+## 검증
+
+Python 3와 Node가 필요하다.
+
+```sh
+make -C prototypes/connections check
+make -C prototypes/connections check-portable
+make -C prototypes/connections check-portable-tui
+make -C prototypes/connections BUILD=build/native-checkpoint check-native-checkpoint
+make -C prototypes/connections check-portable-peer
+make -C prototypes/connections check BUILD=build/sanitized CFLAGS='-std=c17 -O1 -g -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer'
+```
+
+`check-portable`은 C 단위 동작을 검사하며 Linux AArch64의 GNU `size`/`readelf`와
+RSS 상한 검사를 요구하지 않는다. `check-portable-tui`는 고정·소스 정의 편집기를
+실제 PTY에서 검사하며 `/proc` RSS를 읽지 않는다. `check-native-checkpoint`는
+둘을 실행하고 고정·소스 CLI의 실제 1 MiB 생성·읽기·1 B 수정 RSS를 호스트
+단위에 맞춰 기록한다. [기록된 Linux 결과](../../docs/research/060-host-native-checkpoint.md)는
+코어 코드 증가 없이 기존 RSS 상한 검사를 통과했다. 현재 통과 결과는
+Linux AArch64에만 해당한다. 기존 `check-tui`·`check-source-tui`의 Linux
+4,096 KiB RSS 상한 검사는 그대로 유지한다. Apple Silicon 실행과
+디렉터리 동기화·전원 장애 내구성은 별도 검증이 필요하다.
+`check-portable-peer`는 OpenSSL이 준비된 경우에만 선택해서 실행한다. C 피어
+클라이언트·두 서버를 실제 TLS 소켓으로 검증하지만 `/proc` RSS는 수집하지 않는다.
+[휴대형 피어 검사와 Linux 비용](../../docs/research/058-portable-authenticated-peer-check.md)을
+별도로 기록했으며 macOS에서의 통과 결과는 아직 없다.
+
+임시 디렉터리와 실제 루프백 TCP 소켓을 사용한다. 단위 검사에는 범위 접근·페이지 경계·
+이전 참조 유지·공개 전후 실패 주입·공개 전 자식 프로세스 종료가 포함된다. 주입 훅은
+단위 검사 실행 파일에만 들어간다. 실제 두 서버의 쓰기 경쟁과 Workbench 저장·복원 등
+작성에 따른 부분 읽기·쓰기·응답, 한글·이모지 문서 선택, 필드 재배치, 잘린 입력·동적 범위·
+수명 보존을 포함한 28개 통합 시나리오를 일반 빌드와 ASan·UBSan 빌드에서 확인했다.
+준비된 구간과 순차 범위 연산, 숫자 필드의 정렬·바이트 순서·경계 동작도 대조했다.
+
+[검증 자료](results/2026-09-23-field-connections/README.md). 시간·처리량 비교는 수행하지 않았다.
+상수 구간 작성 자료는 [020](results/2026-09-23-prepared-connections/README.md)에 있다.
+작성 기능 도입 전 자료는 [019](results/2026-09-23-byte-storage/README.md)에 있다.
+이전 SQLite 구현의 결과는 [018 자료](results/2026-09-23-native-connections/README.md)에
+별도로 보존했다.
+
+## 이번 변경의 판단 기준
+
+이름 기반 필드·데이터 의존 범위를 실제 저장·응답으로 연결하는
+[착수 기준](../../docs/design/005-field-connections.md)을 확인했다. 다음에는 앱의 읽기·변경·저장
+경로에서 필요한 연산과 버전 관계를 다룬다. 범용 그래프 실행기나 자동 재시도·피드백 루프를
+검증 없이 추가하지 않는다.
diff --git a/prototypes/connections/SOURCE_PREVIEW.md b/prototypes/connections/SOURCE_PREVIEW.md
new file mode 100644
index 0000000..9e0d78d
--- /dev/null
+++ b/prototypes/connections/SOURCE_PREVIEW.md
@@ -0,0 +1,119 @@
+# Pure native source preview
+
+This bundle contains the C17 execution core, the authored document app, its
+CLI and optional terminal/HTTP/TLS hosts, plus the Workbench sources used by
+the integration checks. It excludes prior benchmark results and build outputs.
+`manifest.json` records the exact files and their SHA-256 hashes.
+
+Build and run the small default path from the extracted directory:
+
+```sh
+make -C prototypes/connections check-portable
+make -C prototypes/connections check-portable-tui
+make -C prototypes/connections check-policy
+make -C prototypes/connections fixed-editor fixed-tui
+make -C prototypes/connections source-tui
+mkdir -p /tmp/pure-source-store
+printf 'hello Pure\n' > /tmp/pure-source-insert.txt
+prototypes/connections/build/pure-edit-fixed --store /tmp/pure-source-store \
+ edit note 0 0 0 /tmp/pure-source-insert.txt
+prototypes/connections/build/pure-edit-fixed --store /tmp/pure-source-store show note
+prototypes/connections/build/pure-edit-tui --program \
+ prototypes/connections/examples/editor.pure --store /tmp/pure-source-store note
+```
+
+`check-portable` builds the C hosts and runs the host-neutral C behavior tests.
+`check-portable-tui` runs the fixed and source-loaded terminal editors through
+real PTYs, including UTF-8 input, resize, 1 MiB edits, conflicts and document
+browsing. It records no Linux `/proc` RSS number; on macOS it is a behavior
+check, not a proof of the 4 MiB Linux memory ceiling.
+For a single native checkpoint command, run from the extracted directory:
+
+```sh
+make -C prototypes/connections BUILD=build/native-checkpoint check-native-checkpoint
+```
+
+This requires a C17 compiler, Make and Python 3. It builds the core, CLI and
+TUI, exercises both terminal variants, then records whole-process peak RSS for
+the fixed and source-loaded CLIs during a real 1 MiB document creation, read
+and 1-byte revision edit. To save the two memory results, add
+`PORTABLE_SOURCE_MEMORY_EVIDENCE=/path/source.json` and
+`PORTABLE_FIXED_MEMORY_EVIDENCE=/path/fixed.json` to the `make` command.
+The RSS helper reports the OS raw unit and normalized KiB. No macOS RSS budget
+has been established; compare macOS results only with the same host and build.
+The optional `make -C prototypes/connections check-portable-peer` builds the
+TLS client and two server profiles, then checks mutual authentication, document
+editing, invalid frames and restart over real sockets. It requires OpenSSL
+headers, libraries and command-line tool, and records no RSS in portable mode.
+On Linux AArch64, `make -C prototypes/connections check-release` additionally
+checks the measured code, dependency and process-memory ceilings and the actual
+document/HTTP paths; it needs Python 3, Node.js, and GNU `size`/`readelf`.
+`check-policy` runs the authored final-size guard through the CLI, HTTP and
+terminal hosts; `check-policy-peer` additionally requires OpenSSL and checks
+the same policy over mutually authenticated TLS.
+The source-loading CLI can run a changed `.pure` definition with
+`make -C prototypes/connections editor` and `--program PATH`.
+
+The selected 16 KiB-page document store can be exported into a **new** default
+store directory without linking it into the small default app:
+
+```sh
+make -C prototypes/connections fixed-editor
+make -C prototypes/connections BUILD=build/hybrid STORE=store-paged.c fixed-editor
+python3 prototypes/connections/export_flat_store.py \
+ --source /path/to/paged-store --destination /path/to/new-flat-store \
+ --paged-editor prototypes/connections/build/hybrid/pure-edit-fixed \
+ --flat-editor prototypes/connections/build/pure-edit-fixed
+```
+
+The source stays intact. The tool holds its writer lock during conversion and
+checks every object with the default editor before publishing the destination.
+Writers may receive `busy` until it finishes; schedule this as maintenance.
+The destination must not exist. `make -C prototypes/connections check-flat-export`
+exercises the conversion with real mixed-size and repeatedly edited documents.
+
+On a Linux host with 16 KiB OS pages, the selected hybrid store can also run
+the source-loaded native terminal editor without adding it to the default app:
+
+```sh
+make -C prototypes/connections BUILD=build/hybrid STORE=store-paged.c editor source-tui
+python3 prototypes/connections/package_native.py \
+ --build prototypes/connections/build/hybrid --hybrid-storage --with-tui \
+ --output /tmp/pure-hybrid-tui.tar.gz
+python3 prototypes/connections/check_package.py /tmp/pure-hybrid-tui.tar.gz
+```
+
+Use a new store directory for this profile; large documents use `PUREP001`
+and need the offline exporter above before the default store can read them.
+
+For a same-process connection between real document stores, build the selected
+`storage.pure` mirror and send one source snapshot to one or more destinations:
+
+```sh
+make -C prototypes/connections mirror
+prototypes/connections/build/pure-mirror \
+ /path/to/source-store document /path/to/target-store document 0
+make -C prototypes/connections check-mirror
+```
+
+The final number is the expected target revision. Up to eight targets may be
+specified as store/key/revision triples. Each target commits independently;
+the JSON result reports conflicts and partial success. The mapped source body
+stays alive until every forwarded target releases it. No socket or additional
+target input buffer is involved, and this host is a one-shot command rather
+than a long-running application supervisor. An optional leading
+`--target-budget BYTES` bounds each destination's admitted body size; an
+insufficient budget rejects the transfer before any document write.
+
+The fixed CLI and TUI contain one build-time prepared `editor.pure` and do not
+reload a changed definition. The source TUI loads `.pure` at startup; edit the
+file and start a new session to apply a different definition. The Workbench
+scalar-native build additionally requires Zig 0.15.2; the GTK and TLS hosts
+need their platform libraries.
+On Linux, `make -C prototypes/connections check-copy-range` compares an
+experimental large-extent file copy path with the ordinary bounded-scratch
+build. It needs `strace`, `findmnt` and GNU size tools and has only been validated on the
+recorded Linux kernel and filesystem.
+macOS source compilation and execution are not yet verified. This preview is
+not a signed release, does not bundle system libraries, and does not establish
+a redistribution license.
diff --git a/prototypes/connections/async-core-budget.json b/prototypes/connections/async-core-budget.json
new file mode 100644
index 0000000..d2d4c0b
--- /dev/null
+++ b/prototypes/connections/async-core-budget.json
@@ -0,0 +1,16 @@
+{
+ "profile": "selected-owner-thread-async-effects",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 120,
+ "work_slot_bytes": 216,
+ "ticket_bytes": 24,
+ "pointer_bytes": 8,
+ "effect_bytes": 72
+ },
+ "archive_members": ["runtime-async.o"],
+ "external_symbols_allowed": ["memcpy", "memmove", "memset", "strlen"],
+ "scope": "Selected compact owner-thread completion extension without opt-in PURE_RUNTIME_METRICS. Host I/O and worker stacks are excluded. The default execution core and fixed document packages do not link this profile."
+}
diff --git a/prototypes/connections/async-server-budget.json b/prototypes/connections/async-server-budget.json
new file mode 100644
index 0000000..b1664fc
--- /dev/null
+++ b/prototypes/connections/async-server-budget.json
@@ -0,0 +1,12 @@
+{
+ "profile": "linux-aarch64-gcc14-selected-read-write-document-http",
+ "binaries": {
+ "pure-connections-async": {
+ "max_text_bytes": 49152,
+ "max_data_bytes": 1200,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ }
+ },
+ "scope": "Optional one-read/one-write-worker HTTP host on the recorded Linux AArch64/GCC 14 toolchain. Section limits exclude the two 128 KiB worker stacks, libc, heap, mapped files and kernel buffers. Default CLI and HTTP do not link this option. Inspect process RSS and VM separately."
+}
diff --git a/prototypes/connections/check.py b/prototypes/connections/check.py
new file mode 100644
index 0000000..7719537
--- /dev/null
+++ b/prototypes/connections/check.py
@@ -0,0 +1,552 @@
+#!/usr/bin/env python3
+"""Exercise local TCP, immutable byte extents, and the existing workbench CLI."""
+import argparse
+from contextlib import contextmanager
+from concurrent.futures import ThreadPoolExecutor
+import fcntl
+import hashlib
+import http.client
+import json
+import platform
+from pathlib import Path
+import select
+import socket
+import struct
+import subprocess
+import sys
+import tempfile
+import time
+from check_edits import check_edits
+
+ROOT = Path(__file__).resolve().parent
+WORKBENCH = ROOT.parent / 'workbench'
+OBJECT_LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+class Server:
+ def __init__(self, binary, storage, budget=4 * 1024 * 1024, timeout=5000, program=None):
+ self.process = subprocess.Popen([str(binary), '--store', str(storage), '--port', '0',
+ '--program', str(program or ROOT / 'examples/storage.pure'),
+ '--budget', str(budget), '--timeout-ms', str(timeout), '--send-buffer', '4096'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
+ if not select.select([self.process.stdout], [], [], 15)[0]:
+ self.process.kill()
+ raise AssertionError('server readiness timed out')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.ready = json.loads(line)
+ self.port = self.ready['port']
+ self.stats = None
+
+ def close(self):
+ if self.process.poll() is None:
+ self.process.terminate()
+ try:
+ stdout, stderr = self.process.communicate(timeout=10)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.process.communicate()
+ raise
+ assert self.process.returncode == 0, (stdout, stderr)
+ self.stats = json.loads(stderr)
+ assert self.stats['active'] == self.stats['retained_payload_bytes'] == 0
+ assert self.stats['peak_retained_payload_bytes'] <= self.stats['payload_budget']
+ assert self.stats['peak_connections'] <= 8
+
+
+@contextmanager
+def serving(*args, **kwargs):
+ server = Server(*args, **kwargs)
+ try:
+ yield server
+ finally:
+ server.close()
+
+
+def rpc(server, method, key, body=b'', expected=None):
+ headers = {'Content-Length': str(len(body))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = '*' if expected == 0 else f'"{expected}"'
+ connection = http.client.HTTPConnection('127.0.0.1', server.port, timeout=8)
+ try:
+ connection.request(method, f'/objects/{key}', body, headers)
+ response = connection.getresponse()
+ return response.status, dict(response.getheaders()), response.read()
+ finally:
+ connection.close()
+
+
+def wire(server, request, chunks=None):
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ if chunks:
+ for chunk in chunks:
+ sock.sendall(chunk)
+ else:
+ sock.sendall(request)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ return response.status, dict(response.getheaders()), response.read()
+
+
+def header(method, key, size=0, condition=b''):
+ return (f'{method} /objects/{key} HTTP/1.1\r\nHost: localhost\r\n'
+ f'Content-Length: {size}\r\n'.encode() + condition + b'\r\n')
+
+
+def cli(server, commands, source=None, expected_code=0):
+ result = subprocess.run(['node', str(WORKBENCH / 'cli.mjs'), *([str(source)] if source else [])],
+ input=commands.replace('$URL', f'http://127.0.0.1:{server.port}'), text=True,
+ capture_output=True, timeout=30)
+ assert result.returncode == expected_code, (result.stdout, result.stderr)
+ return [json.loads(line) for line in result.stdout.splitlines()], result.stderr
+
+
+def check(binary, directory, editor=None):
+ storage = directory / 'objects'
+ checks, records = [], []
+ with serving(binary, storage) as server:
+ assert rpc(server, 'GET', 'absent')[0] == 404
+ payload = b'\x00\xffbinary\r\n\r\n' + bytes(range(256)) * 41
+ request = header('PUT', 'binary', len(payload), b'If-None-Match: *\r\n') + payload
+ status, headers, _ = wire(server, request, [request[:7], request[7:51], request[51:57], request[57:]])
+ assert status == 200 and headers['ETag'] == '"1"'
+ assert rpc(server, 'GET', 'binary')[2] == payload
+ checks.append('fragmented request and binary bytes round trip')
+ assert rpc(server, 'PUT', 'binary', b'new', 0)[0] == 412
+ assert rpc(server, 'PUT', 'binary', b'new', 1)[0] == 200
+ assert rpc(server, 'PUT', 'binary', b'stale', 1)[0] == 412
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('conditional create and stale revision preserve committed bytes')
+
+ with (storage / '.writer.lock').open('r+b') as lock:
+ fcntl.lockf(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ assert rpc(server, 'PUT', 'binary', b'blocked', 2)[0] == 503
+ fcntl.lockf(lock, fcntl.LOCK_UN)
+ broken = storage / 'obj-broken'
+ broken.write_bytes(b'incomplete')
+ assert rpc(server, 'GET', 'broken')[0] == 500
+ assert rpc(server, 'PUT', 'broken', b'failure', 0)[0] == 500
+ assert broken.read_bytes() == b'incomplete'
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('writer contention and invalid extent fail without overwriting data')
+
+ with serving(binary, storage) as second_writer:
+ with ThreadPoolExecutor(max_workers=2) as pool:
+ tasks = [pool.submit(rpc, target, 'PUT', 'race', value, 0)
+ for target, value in [(server, b'first'), (second_writer, b'second')]]
+ statuses = [task.result()[0] for task in tasks]
+ assert statuses.count(200) == 1 and all(status in [200, 412, 503] for status in statuses)
+ status, headers, body = rpc(server, 'GET', 'race')
+ assert status == 200 and headers['ETag'] == '"1"' and body in [b'first', b'second']
+ records.append(second_writer.stats)
+ checks.append('two native writers cannot both create the same expected revision')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'incomplete', 100, b'If-None-Match: *\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ sock.close()
+ assert rpc(server, 'GET', 'incomplete')[0] == 404
+ checks.append('incomplete request never commits and releases its allocation')
+
+ # Force genuine partial socket sends. A write on another connection must
+ # not alter the immutable file whose bytes are still being transmitted.
+ large = bytes(range(256)) * 4096
+ assert rpc(server, 'PUT', 'large', large, 0)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.getheader('ETag') == '"1"'
+ assert response.read(17) == large[:17]
+ assert rpc(server, 'PUT', 'large', b'changed', 1)[0] == 200
+ assert response.read() == large[17:]
+ sock.close()
+ assert rpc(server, 'GET', 'large')[2] == b'changed'
+ checks.append('borrowed read remains the same snapshot during another commit')
+
+ assert rpc(server, 'PUT', 'large', large, 2)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ assert sock.recv(1)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ sock.close()
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('receiver reset aborts an outstanding borrowed transfer')
+
+ assert wire(server, header('PUT', 'too_large', OBJECT_LIMIT + 1, b'If-None-Match: *\r\n'))[0] == 413
+ malformed = [
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nContent-Length: 1\r\nContent-Length: 1\r\nIf-None-Match: *\r\n\r\nx',
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n',
+ b'GET /objects/bad HTTP/1.1\r\nHost: x\x00hidden\r\n\r\n',
+ ]
+ for request in malformed:
+ assert wire(server, request)[0] == 400
+ assert rpc(server, 'GET', 'bad')[0] == 404
+ checks.append('unsupported framing and oversized payload are rejected before effects')
+
+ # Existing authoring path: define, manipulate, save remotely, reconstruct
+ # in a fresh runtime. No fabricated project fixture or mock storage.
+ source = WORKBENCH / 'examples' / 'direct.pure'
+ saved = directory / 'restored.json'
+ lines, _ = cli(server, 'point drag down 80 180\npoint drag move 210 210\npoint drag up 210 210\n'
+ 'connect $URL authored\npush 0\nquit\n', source)
+ snapshots = [line for line in lines if 'states' in line]
+ assert snapshots
+ expected_states = snapshots[-1]['states']
+ assert expected_states['x'] == 210 and expected_states['y'] == 190 and expected_states['dragging'] == 0
+ lines, _ = cli(server, f'connect $URL authored\npull\nsave-project {saved}\nquit\n')
+ assert [line for line in lines if 'states' in line][-1]['states'] == expected_states
+ document = json.loads(saved.read_text())
+ assert document['version'] == 2 and document['source'] == source.read_text()
+ lines, error = cli(server, 'connect $URL authored\npush 0\nquit\n', source, 1)
+ assert '412' in error
+ checks.append('existing workbench manipulation restores in a fresh runtime and reports conflict')
+
+ assert rpc(server, 'PUT', 'invalid_project', b'{"format":"pure-workbench","version":2,"source":"state x=1","states":[]}', 0)[0] == 200
+ lines, error = cli(server, 'show\nconnect $URL invalid_project\npull\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and error
+ lines, error = cli(server, 'point drag down 90 170\nconnect $URL authored\npull\npush\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and states[-1]['dragging'] == 1
+ assert len(error.strip().splitlines()) == 2
+ checks.append('invalid or non-idle restore preserves local state and does not adopt remote revision')
+
+ assert rpc(server, 'PUT', 'wide_revision', rpc_bytes(saved), 0)[0] == 200
+ wide = storage / 'obj-wide_revision'
+ raw = wide.read_bytes()
+ wide.write_bytes(raw[:8] + struct.pack('<Q', 9007199254740993) + raw[16:])
+ lines, _ = cli(server, 'connect $URL wide_revision\npull\npush\nquit\n')
+ revisions = [line['revision'] for line in lines if 'remote' in line and 'revision' in line]
+ assert revisions == ['9007199254740993', '9007199254740994']
+ checks.append('revision above JavaScript safe integer round trips without numeric coercion')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'unread_ack', 4, b'If-None-Match: *\r\n') + b'done')
+ try:
+ deadline = time.monotonic() + 3
+ while True:
+ committed = storage / 'obj-unread_ack'
+ if committed.exists():
+ assert rpc(server, 'GET', 'unread_ack')[2] == b'done'
+ break
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ finally:
+ sock.close() # Client never consumes the successful response.
+ assert rpc(server, 'PUT', 'unread_ack', b'again', 0)[0] == 412
+ assert rpc(server, 'GET', 'unread_ack')[2] == b'done'
+ checks.append('unread acknowledgment does not undo commit or permit a stale retry')
+
+ # A disconnect after commit can hide the ACK; retries remain conditional.
+ assert rpc(server, 'PUT', 'empty', b'', 0)[0] == 200
+ assert rpc(server, 'GET', 'empty')[2] == b''
+ checks.append('empty body has a valid lifetime and stored revision')
+ records.append(server.stats)
+
+ with serving(binary, storage) as restarted:
+ assert rpc(restarted, 'GET', 'binary')[2] == b'new'
+ assert rpc(restarted, 'GET', 'authored')[2] == rpc_bytes(saved)
+ checks.append('committed authoring state survives process restart')
+ records.append(restarted.stats)
+
+ # Fixed small payload budget is an admission test, not a throughput workload.
+ with serving(binary, storage, budget=1024 * 1024, timeout=1200) as limited:
+ sock = socket.create_connection(('127.0.0.1', limited.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200
+ assert response.read(1) == large[:1]
+ status, headers, _ = rpc(limited, 'GET', 'large')
+ assert status == 503 and headers['X-Pure-Error'] == 'payload_budget'
+ # Leave the first receiver stalled until the absolute connection deadline.
+ time.sleep(1.4)
+ assert rpc(limited, 'GET', 'binary')[2] == b'new'
+ response.close()
+ sock.close()
+ checks.append('slow consumer retains its lease; budget rejects another; deadline releases it')
+
+ idle = [socket.create_connection(('127.0.0.1', limited.port), timeout=8) for _ in range(8)]
+ try:
+ for s in idle:
+ s.sendall(b'G')
+ for s in idle:
+ assert s.recv(1) == b''
+ finally:
+ for s in idle:
+ s.close()
+ assert rpc(limited, 'GET', 'binary')[0] == 200
+ checks.append('connection slots stay bounded and recover after header deadlines')
+ assert limited.stats['budget_rejections'] >= 1 and limited.stats['expired'] >= 9
+ records.append(limited.stats)
+ prepared = authored_connections(binary, directory, storage, records, checks)
+ fields = field_connections(binary, directory, storage, records, checks)
+ edits = check_edits(editor, binary, ROOT, directory, serving, rpc, header, records, checks) if editor else None
+ return {'kind': 'prepared-connection-correctness-not-performance', 'checks': checks,
+ 'prepared_connections': prepared,
+ 'field_connections': fields,
+ 'document_edits': edits,
+ 'server_runs': records, 'storage': server.ready['storage']}
+
+
+def authored_connections(binary, directory, storage, records, checks):
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); }'
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); }'
+
+ def author(name, source):
+ path = directory / name
+ path.write_text(source)
+ return path
+
+ def explain(path):
+ return json.loads(subprocess.check_output([str(binary), '--check-program', str(path)], text=True))
+
+ with serving(binary, storage) as writer:
+ assert rpc(writer, 'PUT', 'short_parent', bytes(range(48)), 0)[0] == 200
+ assert rpc(writer, 'PUT', 'short_unused', bytes(range(80)), 0)[0] == 200
+ records.append(writer.stats)
+ excerpt = ROOT / 'examples/excerpt.pure'
+ prepared = {'excerpt': explain(excerpt)}
+ assert prepared['excerpt']['read'] == {
+ 'to_end': False, 'offset': 32, 'length': 16, 'minimum_source_bytes': 80}
+ with serving(binary, storage, budget=16, program=excerpt) as selected:
+ status, headers, body = rpc(selected, 'GET', 'large')
+ assert status == 200 and body == bytes(range(32, 48)) and headers['ETag'] == '"3"'
+ # Final [32,48) fits, but the authored parent [16,80) does not.
+ assert rpc(selected, 'GET', 'short_parent')[0] == 413
+ assert rpc(selected, 'GET', 'missing')[0] == 404
+ assert selected.stats['peak_retained_payload_bytes'] == 16
+ records.append(selected.stats)
+ checks.append('authored nested read maps only final demand while preserving parent bounds and revision')
+
+ unused = author('unused.pure', 'on get { let o = store.read(request.key); '
+ 'let unused = range(o.body, 0, 96); let body = range(o.body, 32, 16); reply(o, body); } ' + put)
+ with serving(binary, storage, budget=16, program=unused) as guarded:
+ assert rpc(guarded, 'GET', 'short_unused')[0] == 413
+ assert rpc(guarded, 'GET', 'large')[2] == bytes(range(32, 48))
+ records.append(guarded.stats)
+ checks.append('unused checked view still fails even when response range would be valid')
+
+ select_write = author('write.pure', get + ' on put { let a = range(request.body, 2, 10); '
+ 'let b = range(a, 3, 4); let alias = b; '
+ 'let saved = store.write(request.key, request.revision, alias); reply(saved, b); }')
+ prepared['write'] = explain(select_write)
+ with serving(binary, storage, program=select_write) as writer:
+ status, headers, body = rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'GET', 'selected')[2] == b'5678'
+ assert rpc(writer, 'PUT', 'selected', b'012345678', 1)[0] == 413
+ status, headers, body = rpc(writer, 'GET', 'selected')
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)[0] == 412
+ records.append(writer.stats)
+ checks.append('authored write and reply share selected input; invalid parent prevents the storage effect')
+
+ metadata = author('metadata.pure', 'on get { let o = store.read(request.key); reply(o); } ' + put)
+ with serving(binary, storage, budget=1, program=metadata) as meta:
+ status, headers, body = rpc(meta, 'GET', 'large')
+ assert status == 200 and headers['ETag'] == '"3"' and body == b''
+ assert rpc(meta, 'GET', 'absent')[0] == 404
+ assert rpc(meta, 'GET', 'broken')[0] == 500
+ assert meta.stats['peak_retained_payload_bytes'] == 0
+ records.append(meta.stats)
+ checks.append('body-free response preserves read existence and malformed-object errors')
+
+ echo = author('echo.pure', get + ' on put { let body = request.body; '
+ 'let saved = store.write(request.key, request.revision, body); reply(saved, body); }')
+ payload = bytes(range(256)) * 4096
+ with serving(binary, storage, budget=len(payload), program=echo) as echoed:
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == payload[:1]
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ assert response.read() == payload[1:]
+ response.close()
+ assert rpc(echoed, 'GET', 'binary')[2] == b'new'
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo_abort', len(payload), b'If-None-Match: *\r\n') + payload)
+ assert sock.recv(1)
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ deadline = time.monotonic() + 3
+ while rpc(echoed, 'GET', 'binary')[0] == 503:
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ assert rpc(echoed, 'GET', 'echo_abort')[2] == payload
+ records.append(echoed.stats)
+ checks.append('input-backed response survives partial send and releases on finish or abort without undoing commit')
+
+ bad = author('invalid.pure', get + get + put)
+ untouched = directory / 'must_not_exist'
+ rejected = subprocess.run([str(binary), '--program', str(bad), '--store', str(untouched)],
+ capture_output=True, text=True, timeout=10)
+ assert rejected.returncode == 2 and 'duplicate handler' in rejected.stderr and not untouched.exists()
+ checks.append('invalid authored program fails preparation before creating storage or accepting requests')
+ return prepared
+
+
+def field_connections(binary, directory, storage, records, checks):
+ program = ROOT / 'examples/selection.pure'
+ plans = {'selection': json.loads(subprocess.check_output(
+ [str(binary), '--check-program', str(program)], text=True))}
+ assert plans['selection']['runtime_view_steps'] == 1
+ assert plans['selection']['steps'][0] == {
+ 'source_step': 0, 'source': {'offset': 8, 'length': 0, 'to_end': True},
+ 'offset': {'value': 0, 'from_u32le': True}, 'length': {'value': 4, 'from_u32le': True}}
+ document = '처음🙂 Pure는 필드를 연결한다.\n끝'
+ document_file = directory / 'document.txt'
+ document_file.write_bytes(document.encode('utf-8'))
+ with serving(binary, storage, program=program) as selected:
+ command = [sys.executable, str(ROOT / 'examples/select-text.py'), str(document_file),
+ '--key', 'text_selection', '--start', '2', '--end', '12', '--url', f'http://127.0.0.1:{selected.port}']
+ result = subprocess.run(command, capture_output=True, text=True, timeout=15)
+ assert result.returncode == 0, (result.stdout, result.stderr)
+ expected = document[2:12].encode('utf-8')
+ assert json.loads(result.stdout) == {'revision': '1', 'selected': document[2:12], 'stored_bytes': len(expected)}
+ assert rpc(selected, 'GET', 'text_selection')[2] == expected
+ checks.append('text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes')
+
+ # Validation precedes the write: even a stale header cannot expose or
+ # commit partial input, and prior content/revision survive all failures.
+ invalid = [b'\0' * n for n in range(8)] + [
+ struct.pack('<II', 0xffffffff, 0) + b'abc',
+ struct.pack('<II', 0, 0xffffffff) + b'abc',
+ struct.pack('<II', 2, 2) + b'abc',
+ struct.pack('<II', 4, 0) + b'abc']
+ for payload in invalid:
+ assert rpc(selected, 'PUT', 'text_selection', payload, 1)[0] == 413
+ status, headers, body = rpc(selected, 'GET', 'text_selection')
+ assert status == 200 and headers['ETag'] == '"1"' and body == expected
+ for key, payload in [('selection_empty', struct.pack('<II', 0, 0)),
+ ('selection_end', struct.pack('<II', 3, 0) + b'abc')]:
+ assert rpc(selected, 'PUT', key, payload, 0)[0] == 200
+ assert rpc(selected, 'GET', key)[2] == b''
+ assert rpc(selected, 'PUT', 'text_selection', struct.pack('<II', 0, 3) + b'abc', 0)[0] == 412
+ checks.append('truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid')
+ records.append(selected.stats)
+
+ declaration = 'layout E { tag: bytes[3]; count: u32le; start: u32le; document: bytes; } '
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); } '
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); } '
+ reordered = directory / 'reordered.pure'
+ reordered.write_text(declaration + get + 'on put { let e = view(E, request.body); let alias = e; '
+ 'let part = range(alias.document, alias.start, alias.count); let again = part; '
+ 'let s = store.write(request.key, request.revision, again); reply(s, part); }')
+ plans['reordered'] = json.loads(subprocess.check_output([str(binary), '--check-program', str(reordered)], text=True))
+ assert plans['reordered']['runtime_view_steps'] == 1
+ with serving(binary, storage, program=reordered) as moved:
+ status, headers, body = rpc(moved, 'PUT', 'reordered', b'tag' + struct.pack('<II', 4, 2) + b'abcdefgh', 0)
+ assert status == 200 and body == b'cdef' and headers['ETag'] == '"1"'
+ assert rpc(moved, 'GET', 'reordered')[2] == b'cdef'
+ records.append(moved.stats)
+ checks.append('changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps')
+
+ unused = directory / 'unused-dynamic.pure'
+ unused.write_text(declaration + get + 'on put { let e = view(E, request.body); '
+ 'let unused = range(e.document, e.start, e.count); '
+ 'let s = store.write(request.key, request.revision, e.document); reply(s); }')
+ with serving(binary, storage, program=unused) as guarded:
+ assert rpc(guarded, 'PUT', 'unused_dynamic', b'tag' + struct.pack('<II', 4, 2) + b'abc', 0)[0] == 413
+ assert rpc(guarded, 'GET', 'unused_dynamic')[0] == 404
+ assert rpc(guarded, 'PUT', 'unused_dynamic', b'tag' + struct.pack('<II', 1, 1) + b'abc', 0)[0] == 200
+ assert rpc(guarded, 'GET', 'unused_dynamic')[2] == b'abc'
+ records.append(guarded.stats)
+ checks.append('unused dynamic field selection retains its validation before the write effect')
+
+ field_get = directory / 'field-get.pure'
+ field_get.write_text(declaration + 'on get { let o = store.read(request.key); '
+ 'let e = view(E, o.body); reply(o, e.document); } ' + put)
+ plans['field_get'] = json.loads(subprocess.check_output([str(binary), '--check-program', str(field_get)], text=True))
+ tail = '다른 길이의 문서'.encode('utf-8')
+ with serving(binary, storage, program=field_get) as writer:
+ assert rpc(writer, 'PUT', 'tail', b'tag' + struct.pack('<II', 0, 0) + tail, 0)[0] == 200
+ assert rpc(writer, 'PUT', 'bad_layout', b'short', 0)[0] == 200
+ assert rpc(writer, 'PUT', 'empty_tail', b'tag' + struct.pack('<II', 0, 0), 0)[0] == 200
+ records.append(writer.stats)
+ with serving(binary, storage, budget=len(tail), program=field_get) as reader:
+ assert rpc(reader, 'GET', 'tail')[2] == tail
+ assert rpc(reader, 'GET', 'empty_tail')[2] == b''
+ assert rpc(reader, 'GET', 'bad_layout')[0] == 413
+ assert reader.stats['peak_retained_payload_bytes'] == len(tail)
+ records.append(reader.stats)
+ checks.append('named variable tail reads use the same file version and charge only the selected suffix')
+
+ document_bytes = bytes(range(256)) * 4096
+ payload = struct.pack('<II', 16, len(document_bytes) - 32) + document_bytes
+ with serving(binary, storage, budget=len(payload), program=program) as slow:
+ with socket.create_connection(('127.0.0.1', slow.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'dynamic_slow', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == document_bytes[16:17]
+ assert rpc(slow, 'GET', 'binary')[0] == 503
+ assert response.read() == document_bytes[17:-16]
+ response.close()
+ assert rpc(slow, 'GET', 'binary')[2] == b'new'
+ assert rpc(slow, 'GET', 'dynamic_slow')[2] == document_bytes[16:-16]
+ assert slow.stats['peak_retained_payload_bytes'] == len(payload)
+ records.append(slow.stats)
+ checks.append('data-dependent response keeps and charges the original input through partial transmission')
+ return plans
+
+
+def rpc_bytes(path):
+ # CLI export is pretty JSON; wire export is compact JSON with the same model.
+ return json.dumps(json.loads(path.read_text()), ensure_ascii=False, separators=(',', ':')).encode()
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path, default=ROOT / 'build/pure-connections')
+ parser.add_argument('--output', type=Path)
+ parser.add_argument('--runtime-test', type=Path)
+ parser.add_argument('--splice-test', type=Path)
+ parser.add_argument('--editor', type=Path)
+ parser.add_argument('--store-source', type=Path, default=ROOT / 'store.c')
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ binary = args.server.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-connections-check-') as temporary:
+ result = check(binary, Path(temporary), args.editor.resolve() if args.editor else None)
+ if args.runtime_test:
+ runtime_test = args.runtime_test.resolve()
+ tested = subprocess.run([str(runtime_test)], cwd=ROOT, capture_output=True, text=True, timeout=30)
+ assert tested.returncode == 0, (tested.stdout, tested.stderr)
+ result['execution_core'] = json.loads(tested.stdout)
+ result['execution_core_test_sha256'] = hashlib.sha256(runtime_test.read_bytes()).hexdigest()
+ if args.splice_test:
+ splice_test = args.splice_test.resolve()
+ tested = subprocess.run([str(splice_test)], cwd=ROOT, capture_output=True, text=True, timeout=30)
+ assert tested.returncode == 0, (tested.stdout, tested.stderr)
+ result['document_edit_units'] = json.loads(tested.stdout)
+ result['document_edit_test_sha256'] = hashlib.sha256(splice_test.read_bytes()).hexdigest()
+ if args.editor:
+ result['editor_sha256'] = hashlib.sha256(args.editor.resolve().read_bytes()).hexdigest()
+ result['binary_sha256'] = hashlib.sha256(binary.read_bytes()).hexdigest()
+ result['environment'] = {'platform': platform.platform(), 'machine': platform.machine(),
+ 'python': platform.python_version(), 'node': subprocess.check_output(['node', '--version'], text=True).strip()}
+ result['source_sha256'] = {str(path.relative_to(ROOT.parent.parent)): hashlib.sha256(path.read_bytes()).hexdigest()
+ for path in [args.store_source.resolve(), *(ROOT / name for name in ('flow.c', 'flow.h', 'store.h', 'program.c', 'program.h',
+ 'runtime.c', 'runtime.h', 'result.h', 'evaluate.c', 'store-port.c', 'store-port.h', 'test-runtime.c',
+ 'server.c', 'check.py', 'check_edits.py', 'edit.c', 'test-splice.c',
+ 'test-flow.c', 'test-program.c', 'test-fields.c', 'Makefile',
+ 'core-layout.c', 'check_core.py', 'core-budget.json', 'examples/editor.pure',
+ 'examples/storage.pure', 'examples/excerpt.pure', 'examples/selection.pure', 'examples/select-text.py')),
+ *(WORKBENCH / name for name in ('remote.mjs', 'cli.mjs', 'web/core.wasm', 'web/runtime.mjs',
+ 'web/compiler.mjs', 'web/project.mjs', 'examples/direct.pure'))]}
+ output = json.dumps(result, ensure_ascii=False, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_async_server.py b/prototypes/connections/check_async_server.py
new file mode 100644
index 0000000..28d7a7f
--- /dev/null
+++ b/prototypes/connections/check_async_server.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python3
+"""Exercise snapshot reads, deadlines and shutdown during a held store write."""
+import argparse
+import hashlib
+from contextlib import suppress
+import http.client
+import json
+import os
+from pathlib import Path
+import select
+import socket
+import struct
+import subprocess
+import tempfile
+import time
+
+HERE = Path(__file__).resolve().parent
+
+
+def gated_server(directory, binary):
+ signaled_read, signaled_write = os.pipe()
+ release_read, release_write = os.pipe()
+ environment = os.environ.copy()
+ environment['PURE_TEST_GATE_SIGNAL_FD'] = str(signaled_write)
+ environment['PURE_TEST_GATE_RELEASE_FD'] = str(release_read)
+ process = subprocess.Popen([
+ str(binary), '--store', str(directory),
+ '--program', str(HERE / 'examples/editor.pure'), '--port', '0',
+ '--timeout-ms', '250'
+ ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True,
+ pass_fds=(signaled_write, release_read), env=environment)
+ os.close(signaled_write)
+ os.close(release_read)
+ assert select.select([process.stdout], [], [], 5)[0], 'server did not start'
+ port = json.loads(process.stdout.readline())['port']
+ return process, port, signaled_read, release_write
+
+
+def begin_write(port):
+ connection = socket.create_connection(('127.0.0.1', port), timeout=3)
+ connection.settimeout(3)
+ body = struct.pack('<II', 3, 0) + b'after'
+ header = (b'PUT /objects/gated HTTP/1.1\r\nHost: localhost\r\n'
+ b'If-Match: "1"\r\nContent-Length: 13\r\n\r\n')
+ connection.sendall(header + body)
+ connection.shutdown(socket.SHUT_WR)
+ return connection
+
+
+def await_gate(fd):
+ assert select.select([fd], [], [], 5)[0], 'store worker did not reach gate'
+ assert os.read(fd, 1) == b'\1'
+
+
+def malformed_response(port):
+ with socket.create_connection(('127.0.0.1', port), timeout=3) as connection:
+ connection.settimeout(3)
+ connection.sendall(b'BAD /objects/invalid HTTP/1.1\r\nHost: localhost\r\n\r\n')
+ response = connection.recv(512)
+ assert response.startswith(b'HTTP/1.1 400 '), response
+
+
+def seed_document(directory, editor):
+ source = directory.parent / (directory.name + '-seed')
+ source.write_bytes(b'old')
+ result = subprocess.run([str(editor), '--store', str(directory), 'edit',
+ 'gated', '0', '0', '0', str(source)],
+ capture_output=True, timeout=5)
+ assert result.returncode == 0, result.stderr
+ assert json.loads(result.stdout)['revision'] == '1', result.stdout
+
+
+def read_document(port, expected, revision):
+ client = http.client.HTTPConnection('127.0.0.1', port, timeout=2)
+ try:
+ client.request('GET', '/objects/gated')
+ response = client.getresponse()
+ observed = (response.status, response.getheader('ETag'), response.read())
+ assert observed == (200, f'"{revision}"', expected), observed
+ return {'status': observed[0], 'etag': observed[1],
+ 'body': observed[2].decode('ascii')}
+ finally:
+ client.close()
+
+
+def finish(process, signal_fd, release_fd):
+ output, error = process.communicate(timeout=5)
+ os.close(signal_fd)
+ os.close(release_fd)
+ assert process.returncode == 0, (process.returncode, output, error)
+ stats = json.loads(error.splitlines()[-1])
+ assert stats['active'] == stats['retained_payload_bytes'] == 0, stats
+ return stats
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path,
+ default=HERE / 'build/pure-connections-async-gated')
+ parser.add_argument('--editor', type=Path,
+ default=HERE / 'build/pure-edit-fixed')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ binary = args.server.resolve()
+ editor = args.editor.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-async-server-') as root:
+ first = Path(root) / 'deadline'
+ seed_document(first, editor)
+ process, port, signal_fd, release_fd = gated_server(first, binary)
+ try:
+ pending = begin_write(port)
+ await_gate(signal_fd)
+ before_publication = read_document(port, b'old', 1)
+ # The writer is still held; a read completed independently.
+ assert process.poll() is None
+ malformed_response(port) # Must answer while the store worker is blocked.
+ assert pending.recv(1) == b'' # Deadline releases the caller's ticket.
+ assert process.poll() is None
+ os.write(release_fd, b'1')
+ after_publication = read_document(port, b'oldafter', 2)
+ pending.close()
+ process.terminate()
+ deadline_stats = finish(process, signal_fd, release_fd)
+ assert (deadline_stats['commits'], deadline_stats['gets'], deadline_stats['expired']) == (1, 2, 1), deadline_stats
+ finally:
+ if process.poll() is None:
+ with suppress(OSError):
+ os.write(release_fd, b'1')
+ process.kill()
+ process.wait(timeout=5)
+ with suppress(OSError):
+ os.close(signal_fd)
+ with suppress(OSError):
+ os.close(release_fd)
+
+ second = Path(root) / 'shutdown'
+ seed_document(second, editor)
+ process, port, signal_fd, release_fd = gated_server(second, binary)
+ try:
+ pending = begin_write(port)
+ await_gate(signal_fd)
+ process.terminate()
+ time.sleep(0.1)
+ assert process.poll() is None # Shutdown waits for the in-flight effect.
+ os.write(release_fd, b'1')
+ pending.close()
+ shutdown_stats = finish(process, signal_fd, release_fd)
+ assert shutdown_stats['commits'] == 1, shutdown_stats
+ restored = subprocess.run([str(editor), '--store', str(second),
+ 'show', 'gated'], capture_output=True, timeout=5)
+ assert restored.returncode == 0, restored.stderr
+ assert restored.stdout == b'oldafter', restored.stdout
+ assert json.loads(restored.stderr)['revision'] == '2', restored.stderr
+ finally:
+ if process.poll() is None:
+ with suppress(OSError):
+ os.write(release_fd, b'1')
+ process.kill()
+ process.wait(timeout=5)
+ with suppress(OSError):
+ os.close(signal_fd)
+ with suppress(OSError):
+ os.close(release_fd)
+ result = {'async_http': 'snapshot-read-write-overlap-deadline-recovery-draining-shutdown',
+ 'before_publication': before_publication,
+ 'after_publication': after_publication,
+ 'shutdown_restore': {'revision': '2', 'body': 'oldafter'},
+ 'deadline_stats': deadline_stats, 'shutdown_stats': shutdown_stats,
+ 'test_source_sha256': hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
+ 'gated_test_binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest()}
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.open('x').write(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_copy_path.py b/prototypes/connections/check_copy_path.py
new file mode 100644
index 0000000..1936076
--- /dev/null
+++ b/prototypes/connections/check_copy_path.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+"""Compare one real immutable-file splice with the selected Linux copy path."""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import platform
+import re
+import subprocess
+import tempfile
+
+HERE = Path(__file__).resolve().parent
+SUCCESS = re.compile(r'= (\d+)$')
+
+
+def run(*args):
+ result = subprocess.run([str(arg) for arg in args], capture_output=True,
+ timeout=30, check=True)
+ return result.stdout
+
+
+def inspect(binary, helper, root, initial, patch):
+ store = root / binary.parent.name
+ base = [binary, '--program', HERE / 'examples/editor.pure', '--store', store]
+ run(*base, 'edit', 'large', 0, 0, 0, initial)
+ trace = root / (binary.parent.name + '.trace')
+ run('strace', '-f', '-qq', '-yy', '-e',
+ 'trace=pread64,write,copy_file_range', '-o', trace,
+ *base, 'edit', 'large', 1, 1_048_575, 1, patch)
+ expected = b'A' * 1_048_575 + b'Z'
+ assert run(*base, 'show', 'large') == expected
+
+ lines = trace.read_text().splitlines()
+ reads = [line for line in lines if 'pread64(' in line and '/obj-large>' in line]
+ copies = [line for line in lines if 'copy_file_range(' in line]
+ writes = [line for line in lines if 'write(' in line and '/.pending-' in line]
+ assert all(SUCCESS.search(line) for line in reads + copies + writes)
+
+ measured_store = root / (binary.parent.name + '-rss')
+ measured = [binary, '--program', HERE / 'examples/editor.pure',
+ '--store', measured_store]
+ run(*measured, 'edit', 'large', 0, 0, 0, initial)
+ usage = json.loads(run(helper, *measured, 'edit', 'large', 1, 1_048_575, 1, patch))
+ assert usage['exit_code'] == 0
+ assert run(*measured, 'show', 'large') == expected
+ return {'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest(),
+ 'result_sha256': hashlib.sha256(expected).hexdigest(),
+ 'object_pread_calls': len(reads),
+ 'copy_file_range_calls': len(copies),
+ 'copy_file_range_bytes': sum(int(SUCCESS.search(line)[1]) for line in copies),
+ 'pending_write_calls': len(writes),
+ 'pending_write_bytes': sum(int(SUCCESS.search(line)[1]) for line in writes),
+ 'one_mib_splice_peak_rss_kib': usage['max_rss_kib']}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--baseline', type=Path, required=True)
+ parser.add_argument('--candidate', type=Path, required=True)
+ parser.add_argument('--baseline-helper', type=Path, required=True)
+ parser.add_argument('--candidate-helper', type=Path, required=True)
+ parser.add_argument('--scratch-dir', type=Path, default=HERE / 'build',
+ help='parent filesystem for the actual document stores')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ if platform.system() != 'Linux':
+ parser.error('strace and wait4 RSS evidence require Linux')
+ args.scratch_dir.mkdir(parents=True, exist_ok=True)
+ with tempfile.TemporaryDirectory(prefix='pure-copy-path-',
+ dir=args.scratch_dir.resolve()) as name:
+ root = Path(name)
+ filesystem = run('findmnt', '-T', root, '-no', 'FSTYPE').decode().strip().splitlines()[0]
+ initial, patch = root / 'initial', root / 'patch'
+ initial.write_bytes(b'A' * 1_048_576)
+ patch.write_bytes(b'Z')
+ baseline = inspect(args.baseline.resolve(), args.baseline_helper.resolve(),
+ root, initial, patch)
+ candidate = inspect(args.candidate.resolve(), args.candidate_helper.resolve(),
+ root, initial, patch)
+ assert baseline['result_sha256'] == candidate['result_sha256']
+ assert baseline['copy_file_range_calls'] == 0
+ assert candidate['copy_file_range_bytes'] == 1_048_575
+ assert candidate['object_pread_calls'] < baseline['object_pread_calls']
+ result = {'profile': 'linux-immutable-one-mib-last-byte-splice',
+ 'platform': platform.platform(), 'baseline': baseline,
+ 'candidate': candidate,
+ 'filesystem': filesystem,
+ 'scratch_parent': str(args.scratch_dir.resolve()),
+ 'scope': 'Successful object-file syscalls and child peak RSS; excludes physical device writes, page cache and proof of lower latency.'}
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_core.py b/prototypes/connections/check_core.py
new file mode 100644
index 0000000..321896e
--- /dev/null
+++ b/prototypes/connections/check_core.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+"""Fail when the selected execution core grows past its reviewed cost boundary.
+
+This is a release-build structural check using GNU-compatible ar/nm/size. Run it
+separately from correctness/sanitizer tests; instrumented objects have other costs.
+"""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import platform
+import subprocess
+
+ROOT = Path(__file__).resolve().parent
+
+
+def run(*args):
+ return subprocess.check_output([str(arg) for arg in args], text=True)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--archive', type=Path, required=True)
+ parser.add_argument('--layout', type=Path, required=True)
+ parser.add_argument('--budget', type=Path, default=ROOT / 'core-budget.json')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ budget = json.loads(args.budget.read_text())
+ archive = args.archive.resolve()
+ members = run('ar', 't', archive).splitlines()
+ layout = json.loads(run(args.layout.resolve()))
+ size_output = run('size', archive)
+ rows = [line.split() for line in size_output.splitlines() if line.split() and line.split()[0].isdigit()]
+ if len(rows) != len(members):
+ parser.error('unsupported size output; no footprint claim was made')
+ sizes = {name: sum(int(row[i]) for row in rows) for i, name in enumerate(('text', 'data', 'bss'))}
+ defined = {line.split()[-1] for line in run('nm', '-g', '--defined-only', archive).splitlines()
+ if len(line.split()) >= 3}
+ undefined = {line.split()[-1] for line in run('nm', '-u', archive).splitlines()
+ if len(line.split()) == 2 and line.split()[0] == 'U'}
+ external = sorted(undefined - defined)
+ failures = []
+ if sorted(members) != sorted(budget['archive_members']):
+ failures.append('unexpected archive members')
+ for name, value in sizes.items():
+ if value > budget[f'max_{name}_bytes']:
+ failures.append(f'{name}: {value} > {budget[f"max_{name}_bytes"]}')
+ for name, maximum in budget['layout_max_bytes'].items():
+ if layout[name] > maximum:
+ failures.append(f'{name}: {layout[name]} > {maximum}')
+ extra = set(external) - set(budget['external_symbols_allowed'])
+ if extra:
+ failures.append(f'unexpected dependencies: {sorted(extra)}')
+ result = {'passed': not failures, 'failures': failures, 'budget': budget,
+ 'layout': layout, 'sections': sizes, 'members': members,
+ 'external_symbols': external, 'size_output': size_output,
+ 'archive_sha256': hashlib.sha256(archive.read_bytes()).hexdigest(),
+ 'layout_binary_sha256': hashlib.sha256(args.layout.resolve().read_bytes()).hexdigest(),
+ 'budget_sha256': hashlib.sha256(args.budget.read_bytes()).hexdigest(),
+ 'platform': platform.platform(), 'size_tool': run('size', '--version').splitlines()[0]}
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+ if failures:
+ raise SystemExit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_document_peer.py b/prototypes/connections/check_document_peer.py
new file mode 100644
index 0000000..1472ed7
--- /dev/null
+++ b/prototypes/connections/check_document_peer.py
@@ -0,0 +1,273 @@
+#!/usr/bin/env python3
+"""Real TLS, document work, external client and CLI interop for the optional peer."""
+import argparse
+import json
+from pathlib import Path
+import select
+import socket
+import ssl
+import struct
+import subprocess
+import tempfile
+
+ROOT = Path(__file__).resolve().parent
+
+
+def openssl(*args):
+ subprocess.run(['openssl', *map(str, args)], check=True,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+
+def certificates(root):
+ ca = root / 'ca.pem'
+ openssl('req', '-x509', '-newkey', 'ec', '-pkeyopt', 'ec_paramgen_curve:P-256',
+ '-nodes', '-days', '1', '-subj', '/CN=Pure test CA',
+ '-addext', 'basicConstraints=critical,CA:TRUE',
+ '-addext', 'keyUsage=critical,keyCertSign,cRLSign',
+ '-keyout', root / 'ca.key', '-out', ca)
+ for role, name, eku in [('server', 'localhost', 'serverAuth'),
+ ('client', 'pure-client', 'clientAuth'),
+ ('other', 'wrong-client', 'clientAuth')]:
+ ext = root / (role + '.ext')
+ ext.write_text('basicConstraints=critical,CA:FALSE\n'
+ 'keyUsage=critical,digitalSignature\n'
+ f'subjectAltName=DNS:{name}\nextendedKeyUsage={eku}\n')
+ openssl('req', '-newkey', 'ec', '-pkeyopt', 'ec_paramgen_curve:P-256',
+ '-nodes', '-subj', '/CN=' + name, '-keyout', root / (role + '.key'),
+ '-out', root / (role + '.csr'))
+ openssl('x509', '-req', '-in', root / (role + '.csr'), '-CA', ca,
+ '-CAkey', root / 'ca.key', '-CAcreateserial', '-days', '1',
+ '-extfile', ext, '-out', root / (role + '.pem'))
+ return ca
+
+
+def start(binary, program, store, root, ca):
+ proc = subprocess.Popen([str(binary), 'serve', '127.0.0.1', '0', str(program),
+ str(store), str(ca), str(root / 'server.pem'),
+ str(root / 'server.key'), 'pure-client'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ text=True, bufsize=1)
+ try:
+ assert select.select([proc.stdout], [], [], 5)[0], 'server did not become ready'
+ line = proc.stdout.readline()
+ assert line.startswith('READY '), (line, proc.poll())
+ return proc, int(line.split()[1])
+ except BaseException as error:
+ proc.kill()
+ stdout, stderr = proc.communicate(timeout=3)
+ raise AssertionError(f'server start failed: {error}; stdout={stdout!r}, stderr={stderr!r}') from error
+
+
+def stop(proc):
+ proc.terminate()
+ stdout, stderr = proc.communicate(timeout=5)
+ assert proc.returncode == 0, (proc.returncode, stdout, stderr)
+
+
+def connect(root, ca, port, *, cert='client', alpn='pure-doc/1', name='localhost'):
+ ctx = ssl.create_default_context(cafile=str(ca))
+ ctx.minimum_version = ssl.TLSVersion.TLSv1_3
+ ctx.maximum_version = ssl.TLSVersion.TLSv1_3
+ if cert:
+ ctx.load_cert_chain(str(root / (cert + '.pem')), str(root / (cert + '.key')))
+ ctx.set_alpn_protocols([alpn])
+ plain = socket.create_connection(('127.0.0.1', port), timeout=5)
+ try:
+ secure = ctx.wrap_socket(plain, server_hostname=name)
+ secure.settimeout(7)
+ if secure.selected_alpn_protocol() != alpn:
+ raise ssl.SSLError('ALPN mismatch')
+ return secure
+ except BaseException:
+ plain.close()
+ raise
+
+
+def exact(sock, count):
+ parts = []
+ while count:
+ part = sock.recv(count)
+ if not part:
+ raise EOFError('unexpected EOF')
+ parts.append(part)
+ count -= len(part)
+ return b''.join(parts)
+
+
+def hello(sock, program):
+ import hashlib
+ assert exact(sock, 40) == b'PDOC\x01\0\0\0' + hashlib.sha256(program.read_bytes()).digest()
+
+
+def request(sock, op, key, expected=0, body=b'', *, pieces=False, want_body=True):
+ key = key.encode('ascii')
+ wire = struct.pack('!BBQI', op | (0x80 if want_body else 0), len(key),
+ expected, len(body)) + key + body
+ if pieces:
+ for at in range(0, len(wire), 4093):
+ sock.sendall(wire[at:at + 4093])
+ else:
+ sock.sendall(wire)
+ status, revision, length = struct.unpack('!BQI', exact(sock, 13))
+ assert length <= 1450000, length
+ return status, revision, exact(sock, length if want_body else 0), length
+
+
+def edit(offset, remove, inserted):
+ return struct.pack('<II', offset, remove) + inserted
+
+
+def call(binary, root, ca, program, port, *command):
+ return subprocess.run([str(binary), 'call', '127.0.0.1', str(port), 'localhost',
+ str(program), str(ca), str(root / 'client.pem'),
+ str(root / 'client.key'), *map(str, command)],
+ capture_output=True, timeout=15)
+
+
+def rss_kib(pid, portable=False):
+ if portable:
+ return None
+ for line in Path(f'/proc/{pid}/status').read_text().splitlines():
+ if line.startswith('VmRSS:'):
+ return int(line.split()[1])
+ raise AssertionError('VmRSS unavailable')
+
+
+def check(binary, editor, program, root, ca, *, server=None, portable=False):
+ if server is None:
+ server = binary
+ store = root / 'objects'
+ proc, port = start(server, program, store, root, ca)
+ checks = []
+ try:
+ baseline = rss_kib(proc.pid, portable)
+ for bad in ({'cert': None}, {'cert': 'other'}, {'alpn': 'pure/1'}, {'name': 'wrong.local'}):
+ try:
+ with connect(root, ca, port, **bad) as sock:
+ hello(sock, program)
+ except (ssl.SSLError, EOFError, ConnectionResetError, BrokenPipeError):
+ pass
+ else:
+ raise AssertionError(f'unauthorized connection succeeded: {bad}')
+ checks.append('mutual certificate identity, server hostname and ALPN separation')
+
+ changed = root / 'different.pure'
+ changed.write_bytes(program.read_bytes() + b'\n')
+ with connect(root, ca, port) as sock:
+ try:
+ hello(sock, changed)
+ except AssertionError:
+ pass
+ else:
+ raise AssertionError('different program source was accepted by C client contract')
+ bad_client = call(binary, root, ca, changed, port, 'show', 'note')
+ assert bad_client.returncode == 2 and b'definition mismatch' in bad_client.stderr.lower()
+ checks.append('program source identity checked before C client sends work')
+
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ assert request(sock, 1, 'note') == (1, 0, b'', 0)
+ assert request(sock, 2, 'note', 0, edit(0, 0, b'hello')) == (0, 1, b'hello', 5)
+ assert request(sock, 1, 'note') == (0, 1, b'hello', 5)
+ assert request(sock, 2, 'note', 0, edit(5, 0, b'wrong')) == (2, 1, b'', 0)
+ assert request(sock, 1, 'note') == (0, 1, b'hello', 5)
+ checks.append('persistent external TLS client: create, read, conflict and recovery')
+
+ insert = root / 'insert.bin'
+ insert.write_bytes(b' world')
+ result = call(binary, root, ca, program, port, 'edit', 'note', '1', '5', '0', insert)
+ assert result.returncode == 0, result.stderr
+ assert json.loads(result.stdout)['revision'] == '2'
+ local = subprocess.run([str(editor), '--program', str(program), '--store', str(store),
+ 'show', 'note'], capture_output=True, timeout=5)
+ assert local.returncode == 0 and local.stdout == b'hello world', local.stderr
+ checks.append('native peer edit and local CLI use the same authored document and storage')
+
+ full = b'a' * (1024 * 1024)
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ assert request(sock, 2, 'note', 2, edit(0, 11, full), pieces=True,
+ want_body=False) == (0, 3, b'', len(full))
+ assert request(sock, 1, 'note') == (0, 3, full, len(full))
+ assert request(sock, 2, 'note', 3, edit(len(full) - 1, 1, b'Z')) == (0, 4, b'Z', 1)
+ assert request(sock, 1, 'note') == (0, 4, full[:-1] + b'Z', len(full))
+ checks.append('fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice')
+ large_file = root / 'large.bin'
+ large_file.write_bytes(full)
+ native = call(binary, root, ca, program, port, 'edit', 'native-large', '0', '0', '0', large_file)
+ assert native.returncode == 0, native.stderr
+ assert json.loads(native.stdout) == {'revision': '1', 'reply_bytes': len(full)}
+ assert len(native.stdout) < 100
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ assert request(sock, 1, 'native-large') == (0, 1, full, len(full))
+ checks.append('native C peer uploads 1 MiB and receives only the requested metadata')
+ large_rss = rss_kib(proc.pid, portable)
+
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ partial = struct.pack('!BBQI', 2, 4, 4, 100) + b'note' + b'\0' * 3
+ sock.sendall(partial)
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ assert request(sock, 1, 'note') == (0, 4, full[:-1] + b'Z', len(full))
+ sock.sendall(struct.pack('!BBQI', 77, 4, 0, 0) + b'note')
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ sock.sendall(struct.pack('!BBQI', 0x82, 4, 4, 1450001) + b'note')
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ assert request(sock, 1, 'note') == (0, 4, full[:-1] + b'Z', len(full))
+ checks.append('incomplete, invalid and oversized frames do not publish a change')
+
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ sock.settimeout(7)
+ assert sock.recv(1) == b''
+ checks.append('idle authenticated session closes after deadline')
+ finally:
+ stop(proc)
+
+ proc, port = start(server, program, store, root, ca)
+ try:
+ with connect(root, ca, port) as sock:
+ hello(sock, program)
+ assert request(sock, 1, 'note') == (0, 4, full[:-1] + b'Z', len(full))
+ result = call(binary, root, ca, program, port, 'show', 'note')
+ assert result.returncode == 0 and result.stdout == full[:-1] + b'Z', result.stderr
+ finally:
+ stop(proc)
+ checks.append('server restart and native C peer preserve the committed large document')
+ return {'profile': 'selected-authenticated-document-peer', 'checks': checks,
+ 'server_idle_rss_kib': baseline, 'server_after_large_work_rss_kib': large_rss,
+ 'portable': portable}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--peer', type=Path, default=ROOT / 'build/pure-document-peer')
+ parser.add_argument('--server', type=Path,
+ help='optional alternate server; --peer remains the native client')
+ parser.add_argument('--editor', type=Path, default=ROOT / 'build/pure-edit')
+ parser.add_argument('--program', type=Path, default=ROOT / 'examples/editor.pure')
+ parser.add_argument('--portable', action='store_true',
+ help='run the full TLS scenarios without Linux /proc RSS measurement')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ with tempfile.TemporaryDirectory(prefix='pure-document-peer-') as tmp:
+ root = Path(tmp)
+ ca = certificates(root)
+ result = check(args.peer.resolve(), args.editor.resolve(), args.program.resolve(), root, ca,
+ server=args.server.resolve() if args.server else None,
+ portable=args.portable)
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_document_server_package.py b/prototypes/connections/check_document_server_package.py
new file mode 100644
index 0000000..44f7bed
--- /dev/null
+++ b/prototypes/connections/check_document_server_package.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+"""Exercise an extracted server-only TLS artifact with an external client."""
+import argparse
+import json
+from pathlib import Path
+import ssl
+import struct
+import subprocess
+import tempfile
+
+import check_document_peer as peer
+
+
+def local_show(editor, program, store, key):
+ result = subprocess.run([str(editor), '--program', str(program), '--store',
+ str(store), 'show', key], capture_output=True, timeout=15)
+ assert result.returncode == 0, (result.returncode, result.stderr)
+ return result.stdout
+
+
+def check(server_binary, editor, program):
+ with tempfile.TemporaryDirectory(prefix='pure-packaged-document-server-') as name:
+ root = Path(name)
+ ca = peer.certificates(root)
+ store = root / 'objects'
+ server, port = peer.start(server_binary, program, store, root, ca)
+ checks = []
+ try:
+ idle_rss = peer.rss_kib(server.pid)
+ for bad in ({'cert': None}, {'cert': 'other'}, {'alpn': 'pure/1'},
+ {'name': 'wrong.local'}):
+ try:
+ with peer.connect(root, ca, port, **bad) as sock:
+ peer.hello(sock, program)
+ except (ssl.SSLError, EOFError, ConnectionResetError, BrokenPipeError):
+ pass
+ else:
+ raise AssertionError(f'unauthorized session succeeded: {bad}')
+ checks.append('relocated server rejects invalid client identity, ALPN and hostname')
+
+ with peer.connect(root, ca, port) as sock:
+ peer.hello(sock, program)
+ assert peer.request(sock, 1, 'note') == (1, 0, b'', 0)
+ assert peer.request(sock, 2, 'note', 0, peer.edit(0, 0, b'hello'),
+ want_body=False) == (0, 1, b'', 5)
+ assert peer.request(sock, 1, 'note') == (0, 1, b'hello', 5)
+ assert peer.request(sock, 2, 'note', 0, peer.edit(5, 0, b'wrong')) == (2, 1, b'', 0)
+ assert local_show(editor, program, store, 'note') == b'hello'
+ checks.append('external client and extracted CLI share a conditional document')
+
+ large = b'a' * (1024 * 1024)
+ with peer.connect(root, ca, port) as sock:
+ peer.hello(sock, program)
+ assert peer.request(sock, 2, 'note', 1, peer.edit(0, 5, large),
+ pieces=True, want_body=False) == (0, 2, b'', len(large))
+ assert peer.request(sock, 1, 'note') == (0, 2, large, len(large))
+ assert peer.request(sock, 2, 'note', 2,
+ peer.edit(len(large) - 1, 1, b'Z')) == (0, 3, b'Z', 1)
+ expected = large[:-1] + b'Z'
+ assert local_show(editor, program, store, 'note') == expected
+ large_rss = peer.rss_kib(server.pid)
+ checks.append('fragmented one MiB ingress, selected reply and CLI-visible splice')
+
+ with peer.connect(root, ca, port) as sock:
+ peer.hello(sock, program)
+ sock.sendall(struct.pack('!BBQI', 2, 4, 3, 100) + b'note' + b'abc')
+ with peer.connect(root, ca, port) as sock:
+ peer.hello(sock, program)
+ assert peer.request(sock, 1, 'note') == (0, 3, expected, len(expected))
+ sock.sendall(struct.pack('!BBQI', 77, 4, 0, 0) + b'note')
+ assert local_show(editor, program, store, 'note') == expected
+ checks.append('truncated and invalid frames do not publish a change')
+ finally:
+ peer.stop(server)
+
+ server, port = peer.start(server_binary, program, store, root, ca)
+ try:
+ with peer.connect(root, ca, port) as sock:
+ peer.hello(sock, program)
+ assert peer.request(sock, 1, 'note') == (0, 3, expected, len(expected))
+ finally:
+ peer.stop(server)
+ checks.append('relocated server restart restores the committed one MiB document')
+ return {'profile': 'relocated-server-only-document-peer', 'checks': checks,
+ 'server_idle_rss_kib': idle_rss,
+ 'server_after_large_work_rss_kib': large_rss}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path, required=True)
+ parser.add_argument('--editor', type=Path, required=True)
+ parser.add_argument('--program', type=Path, required=True)
+ args = parser.parse_args()
+ print(json.dumps(check(args.server.resolve(), args.editor.resolve(),
+ args.program.resolve()), indent=2))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_edits.py b/prototypes/connections/check_edits.py
new file mode 100644
index 0000000..1a6dc53
--- /dev/null
+++ b/prototypes/connections/check_edits.py
@@ -0,0 +1,108 @@
+"""Real native automation and HTTP clients editing the same authored document."""
+from concurrent.futures import ThreadPoolExecutor
+import json
+import socket
+import struct
+import subprocess
+
+
+def check_edits(editor, binary, root, directory, serving, rpc, header, records, checks):
+ storage = directory / 'edited-objects'
+ program = root / 'examples/editor.pure'
+ file = directory / 'insertion.bin'
+
+ def local(*args, body=None, code=0, source=program, budget=None):
+ if body is not None:
+ file.write_bytes(body)
+ args = (*args, str(file))
+ command = [str(editor), '--program', str(source), '--store', str(storage)]
+ if budget is not None:
+ command += ['--budget', str(budget)]
+ result = subprocess.run(command + [str(arg) for arg in args], capture_output=True, timeout=20)
+ assert result.returncode == code, (command, args, result.stdout, result.stderr)
+ return result
+
+ initial = 'Pure에서 안녕 🌏\n'.encode()
+ created = local('edit', 'note', 0, 0, 0, body=initial)
+ assert json.loads(created.stdout)['revision'] == '1'
+ start = initial.index('안녕'.encode())
+ inserted = '반가워'.encode()
+ expected = initial[:start] + inserted + initial[start + len('안녕'.encode()):]
+ local('edit', 'note', 1, start, len('안녕'.encode()), body=inserted)
+ shown = local('show', 'note')
+ assert shown.stdout == expected and json.loads(shown.stderr)['revision'] == '2'
+ checks.append('native authored byte edit and fresh native process restore UTF-8 content')
+ stale = local('edit', 'note', 1, 0, 0, body=b'bad', code=3)
+ assert json.loads(stale.stderr) == {'error': 'conflict', 'revision': '2'}
+ local('edit', 'note', 2, 0xffffffff, 0, body=b'bad', code=2)
+ assert local('show', 'note').stdout == expected
+ checks.append('native stale revision and invalid byte position preserve the committed document')
+
+ reordered = directory / 'edit-reordered.pure'
+ reordered.write_text('layout E { tag: bytes[1]; remove: u32le; start: u32le; body: bytes; } '
+ 'on get { let o = store.read(request.key); reply(o, o.body); } '
+ 'on put { let e = view(E, request.body); '
+ 'let s = store.splice(request.key, request.revision, e.start, e.remove, e.body); reply(s, e.body); }')
+ local('edit', 'note', 2, len(expected), 0, body=b'!', source=reordered)
+ expected += b'!'
+ assert local('show', 'note', source=reordered).stdout == expected
+ checks.append('native convenience editor derives unaligned reordered field positions from the authored program')
+
+ custom = directory / 'edit-custom.pure'
+ custom.write_text('on get { let o = store.read(request.key); reply(o, o.body); } '
+ 'on put { let s = store.splice(request.key, request.revision, 0, 0, request.body); reply(s); }')
+ local('edit', 'custom', 0, 0, 0, body=b'ignored', source=custom, code=2)
+ applied = local('apply', 'custom', 0, body=b'custom input', source=custom)
+ assert json.loads(applied.stdout) == {'revision': '1', 'reply_bytes': 0}
+ assert local('show', 'custom', source=custom).stdout == b'custom input'
+ checks.append('raw native apply runs another authored input contract without changing the executor')
+
+ with serving(binary, storage, program=program) as server:
+ assert rpc(server, 'GET', 'note')[2] == expected
+ status, headers, body = rpc(server, 'PUT', 'note', struct.pack('<II', len(expected), 0) + b'?', 3)
+ assert status == 200 and headers['ETag'] == '"4"' and body == b'?'
+ expected += b'?'
+ assert local('show', 'note').stdout == expected
+ local('edit', 'note', 4, 0, 4, body=b'PURE')
+ expected = b'PURE' + expected[4:]
+ assert rpc(server, 'PUT', 'note', struct.pack('<II', 0, 0) + b'stale', 4)[0] == 412
+ assert rpc(server, 'GET', 'note')[2] == expected
+ checks.append('native CLI and external HTTP share revisions and the same authored storage effect in both directions')
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'note', 12, b'If-Match: "5"\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ assert rpc(server, 'PUT', 'note', b'short', 5)[0] == 413
+ assert rpc(server, 'PUT', 'note', struct.pack('<II', 0xffffffff, 0), 5)[0] == 413
+ assert rpc(server, 'GET', 'note')[2] == expected
+ checks.append('partial or invalid edit input never modifies the stored document')
+ with serving(binary, storage, program=program) as other:
+ with ThreadPoolExecutor(max_workers=2) as pool:
+ tasks = [pool.submit(rpc, target, 'PUT', 'note', struct.pack('<II', 0, 0) + value, 5)
+ for target, value in ((server, b'A'), (other, b'B'))]
+ statuses = [task.result()[0] for task in tasks]
+ assert statuses.count(200) == 1 and all(status in (200, 412, 503) for status in statuses)
+ status, headers, body = rpc(server, 'GET', 'note')
+ assert status == 200 and headers['ETag'] == '"6"'
+ assert body == (b'A' if statuses[0] == 200 else b'B') + expected
+ records.append(other.stats)
+ checks.append('two processes cannot both splice the same expected document revision')
+ records.append(server.stats)
+
+ # This tests retained input size for a real large edit, not throughput.
+ large = bytes(range(256)) * 4096
+ local('edit', 'large', 0, 0, 0, body=large)
+ local('edit', 'large', 1, 524287, 3, body=b'XYZ', budget=11)
+ expected_large = large[:524287] + b'XYZ' + large[524290:]
+ assert local('show', 'large').stdout == expected_large
+ with serving(binary, storage, program=program, budget=11) as bounded:
+ status, headers, body = rpc(bounded, 'PUT', 'large', struct.pack('<II', 524287, 3) + b'abc', 2)
+ assert status == 200 and headers['ETag'] == '"3"' and body == b'abc'
+ assert rpc(bounded, 'PUT', 'large', struct.pack('<II', 0, 0) + b'abcd', 3)[0] == 503
+ assert bounded.stats['peak_retained_payload_bytes'] == 11
+ records.append(bounded.stats)
+ assert local('show', 'large').stdout == large[:524287] + b'abc' + large[524290:]
+ checks.append('1 MiB document changes with 11 input credits; larger input is rejected before an effect')
+ return {'large_document_bytes': len(large), 'small_edit_input_bytes': 11,
+ 'storage_rewrites_full_extent': True, 'storage_scratch_bytes': 4096,
+ 'kind': 'correctness-and-admission-not-total-memory-or-performance'}
diff --git a/prototypes/connections/check_fixed_program.py b/prototypes/connections/check_fixed_program.py
new file mode 100644
index 0000000..3c6941b
--- /dev/null
+++ b/prototypes/connections/check_fixed_program.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python3
+"""Compare the authored and parser-free runners on real document operations."""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import struct
+import subprocess
+import tempfile
+
+HERE = Path(__file__).resolve().parent
+
+
+def run(binary, store, program, *args):
+ command = [str(binary)]
+ if program is not None:
+ command += ['--program', str(program)]
+ command += ['--store', str(store), *map(str, args)]
+ return subprocess.run(command, capture_output=True, timeout=15)
+
+
+def same_call(source, fixed, source_store, fixed_store, program, *args):
+ original = run(source, source_store, program, *args)
+ prepared = run(fixed, fixed_store, None, *args)
+ assert (original.returncode, original.stdout, original.stderr) == (
+ prepared.returncode, prepared.stdout, prepared.stderr), (
+ args, original, prepared)
+ return prepared
+
+
+def check(build, selection_build, excerpt_build):
+ source = (build / 'pure-edit').resolve()
+ fixed = (build / 'pure-edit-fixed').resolve()
+ selected = (selection_build / 'pure-edit-fixed').resolve()
+ excerpt_fixed = (excerpt_build / 'pure-edit-fixed').resolve()
+ compiler = (build / 'pure-compile').resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-fixed-program-') as name:
+ root = Path(name)
+ source_store, fixed_store = root / 'source', root / 'fixed'
+ editor = HERE / 'examples/editor.pure'
+ small = root / 'small'
+ small.write_bytes(b'alpha')
+ first = same_call(source, fixed, source_store, fixed_store, editor,
+ 'edit', 'note', '0', '0', '0', small)
+ assert first.returncode == 0
+ assert same_call(source, fixed, source_store, fixed_store, editor,
+ 'show', 'note').stdout == b'alpha'
+ small.write_bytes(b'XY')
+ assert same_call(source, fixed, source_store, fixed_store, editor,
+ 'edit', 'note', '1', '2', '2', small).returncode == 0
+ assert same_call(source, fixed, source_store, fixed_store, editor,
+ 'edit', 'note', '1', '0', '0', small).returncode == 3
+ assert same_call(source, fixed, source_store, fixed_store, editor,
+ 'edit', 'note', '2', '500', '0', small).returncode != 0
+ assert same_call(source, fixed, source_store, fixed_store, editor,
+ 'show', 'note').stdout == b'alXYa'
+
+ one_mib = root / 'one-mib'
+ one_mib.write_bytes(b'A' * 1_048_576)
+ assert same_call(source, fixed, source_store, fixed_store, editor,
+ 'edit', 'large', '0', '0', '0', one_mib).returncode == 0
+ small.write_bytes(b'Z')
+ assert same_call(source, fixed, source_store, fixed_store, editor,
+ 'edit', 'large', '1', '1048575', '1', small).returncode == 0
+ assert same_call(source, fixed, source_store, fixed_store, editor,
+ 'show', 'large').stdout == b'A' * 1_048_575 + b'Z'
+
+ selection = HERE / 'examples/selection.pure'
+ input_file = root / 'selection-input'
+ input_file.write_bytes(struct.pack('<II', 2, 3) + b'abcdef')
+ selected_store = root / 'selected'
+ authored_store = root / 'authored-selected'
+ assert same_call(source, selected, authored_store, selected_store,
+ selection, 'apply', 'value', '0', input_file).returncode == 0
+ assert same_call(source, selected, authored_store, selected_store,
+ selection, 'show', 'value').stdout == b'cde'
+
+ excerpt = HERE / 'examples/excerpt.pure'
+ excerpt_input = root / 'excerpt-input'
+ excerpt_input.write_bytes(bytes(range(79)))
+ excerpt_source_store, excerpt_fixed_store = root / 'excerpt-source', root / 'excerpt-fixed'
+ assert same_call(source, excerpt_fixed, excerpt_source_store,
+ excerpt_fixed_store, excerpt,
+ 'apply', 'sample', '0', excerpt_input).returncode == 0
+ assert same_call(source, excerpt_fixed, excerpt_source_store,
+ excerpt_fixed_store, excerpt, 'show', 'sample').returncode != 0
+ excerpt_input.write_bytes(bytes(range(80)))
+ assert same_call(source, excerpt_fixed, excerpt_source_store,
+ excerpt_fixed_store, excerpt,
+ 'apply', 'sample', '1', excerpt_input).returncode == 0
+ assert same_call(source, excerpt_fixed, excerpt_source_store,
+ excerpt_fixed_store, excerpt, 'show', 'sample').stdout == bytes(range(32, 48))
+ input_file.write_bytes(struct.pack('<II', 2, 300) + b'abcdef')
+ assert same_call(source, selected, authored_store, selected_store,
+ selection, 'apply', 'value', '1', input_file).returncode != 0
+ assert same_call(source, selected, authored_store, selected_store,
+ selection, 'show', 'value').stdout == b'cde'
+
+ generated = root / 'plan.h'
+ generated.write_bytes(b'prior validated plan\n')
+ invalid = root / 'invalid.pure'
+ invalid.write_bytes(b'on put { broken }\n')
+ attempt = subprocess.run([str(compiler), str(invalid), str(generated)],
+ capture_output=True, timeout=15)
+ assert attempt.returncode != 0 and generated.read_bytes() == b'prior validated plan\n'
+ same_path = root / 'source.pure'
+ same_path.write_bytes(editor.read_bytes())
+ attempt = subprocess.run([str(compiler), str(same_path), str(same_path)],
+ capture_output=True, timeout=15)
+ assert attempt.returncode != 0 and same_path.read_bytes() == editor.read_bytes()
+
+ # A changed FIXED_PROGRAM in one build directory must never silently
+ # reuse the previous embedded plan.
+ switched_build = root / 'reconfigured-build'
+ digests = []
+ for definition in ('editor', 'selection', 'editor'):
+ command = ['make', '-C', str(HERE), f'BUILD={switched_build}',
+ f'FIXED_PROGRAM=examples/{definition}.pure', 'fixed-editor']
+ built = subprocess.run(command, capture_output=True, timeout=30)
+ assert built.returncode == 0, built.stderr[-1000:]
+ digests.append(hashlib.sha256((switched_build / 'pure-edit-fixed').read_bytes()).hexdigest())
+ assert digests[0] != digests[1] and digests[0] == digests[2]
+
+ symbols = subprocess.run(['nm', '-g', str(fixed)], capture_output=True,
+ text=True, check=True, timeout=15).stdout
+ assert 'pure_program_parse' not in symbols and 'pure_program_load' not in symbols
+ return {'profile': 'build-time-prepared-native-document-runner',
+ 'editor_create_edit_conflict_large_restore': 'pass',
+ 'dynamic_selection_and_invalid_range': 'pass',
+ 'nested_read_and_required_extent': 'pass',
+ 'invalid_compilation_preserves_previous_plan': 'pass',
+ 'compiler_rejects_source_as_output': 'pass',
+ 'same_directory_program_switch_rebuilds': 'pass',
+ 'runtime_parser_symbols_absent': 'pass',
+ 'fixed_sha256': hashlib.sha256(fixed.read_bytes()).hexdigest(),
+ 'source_sha256': hashlib.sha256(source.read_bytes()).hexdigest(),
+ 'selection_sha256': hashlib.sha256(selected.read_bytes()).hexdigest(),
+ 'excerpt_sha256': hashlib.sha256(excerpt_fixed.read_bytes()).hexdigest()}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--build', type=Path, default=HERE / 'build')
+ parser.add_argument('--selection-build', type=Path,
+ default=HERE / 'build/fixed-selection')
+ parser.add_argument('--excerpt-build', type=Path,
+ default=HERE / 'build/fixed-excerpt')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ result = check(args.build, args.selection_build, args.excerpt_build)
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_fixed_server.py b/prototypes/connections/check_fixed_server.py
new file mode 100644
index 0000000..369a5a7
--- /dev/null
+++ b/prototypes/connections/check_fixed_server.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python3
+"""Run one document app through parser-free HTTP, source HTTP, and native CLI."""
+import argparse
+import hashlib
+import http.client
+import json
+from pathlib import Path
+import select
+import socket
+import struct
+import subprocess
+import tempfile
+import time
+
+HERE = Path(__file__).resolve().parent
+PEAK_RSS_LIMIT_KIB = 4096
+
+
+class Host:
+ def __init__(self, binary, store, fixed, budget=None, timeout_ms=10000):
+ args = [str(binary), '--store', str(store), '--port', '0',
+ '--send-buffer', '4096', '--timeout-ms', str(timeout_ms)]
+ if budget is not None:
+ args += ['--budget', str(budget)]
+ if not fixed:
+ args += ['--program', str(HERE / 'examples/editor.pure')]
+ self.process = subprocess.Popen(args, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ ready, _, _ = select.select([self.process.stdout], [], [], 10)
+ if not ready:
+ self.process.kill()
+ raise AssertionError('HTTP host did not become ready')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.port = json.loads(line)['port']
+
+ def close(self):
+ self.process.terminate()
+ _, error = self.process.communicate(timeout=10)
+ assert self.process.returncode == 0, error[-1000:]
+ stats = json.loads(error)
+ assert stats['active'] == stats['retained_payload_bytes'] == 0
+ return stats
+
+
+def request(host, method, key, body=b'', expected=None):
+ headers = {'Content-Length': str(len(body))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = (
+ '*' if expected == 0 else f'"{expected}"')
+ connection = http.client.HTTPConnection('127.0.0.1', host.port, timeout=15)
+ try:
+ connection.request(method, f'/objects/{key}', body, headers)
+ response = connection.getresponse()
+ return response.status, response.getheader('ETag'), response.read()
+ finally:
+ connection.close()
+
+
+def splice(offset, remove, insert):
+ return struct.pack('<II', offset, remove) + insert
+
+
+def memory_kib(pid, field='VmRSS:'):
+ for line in Path(f'/proc/{pid}/status').read_text().splitlines():
+ if line.startswith(field):
+ return int(line.split()[1])
+ raise AssertionError(f'{field} unavailable')
+
+
+def check(build):
+ fixed_binary = (build / 'pure-connections-fixed').resolve()
+ source_binary = (build / 'pure-connections').resolve()
+ editor = (build / 'pure-edit-fixed').resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-fixed-http-') as directory:
+ root = Path(directory)
+ store = root / 'store'
+ fixed = Host(fixed_binary, store, True)
+ source = Host(source_binary, store, False)
+ fixed_idle_rss = memory_kib(fixed.process.pid)
+ source_idle_rss = memory_kib(source.process.pid)
+ try:
+ assert request(fixed, 'PUT', 'note', splice(0, 0, b'hello'), 0) == (
+ 200, '"1"', b'hello')
+ assert request(source, 'GET', 'note') == (200, '"1"', b'hello')
+ assert request(source, 'PUT', 'note', splice(5, 0, b' Pure'), 1) == (
+ 200, '"2"', b' Pure')
+ assert request(fixed, 'GET', 'note') == (200, '"2"', b'hello Pure')
+ stale_fixed = request(fixed, 'PUT', 'note', splice(0, 0, b'bad'), 1)
+ stale_source = request(source, 'PUT', 'note', splice(0, 0, b'bad'), 1)
+ assert stale_fixed == stale_source and stale_fixed[0] == 412
+ bad_fixed = request(fixed, 'PUT', 'note', splice(1000, 0, b'bad'), 2)
+ bad_source = request(source, 'PUT', 'note', splice(1000, 0, b'bad'), 2)
+ assert bad_fixed == bad_source and bad_fixed[0] != 200
+ assert request(fixed, 'GET', 'note') == (200, '"2"', b'hello Pure')
+
+ large = b'A' * 1_048_576
+ assert request(fixed, 'PUT', 'large', splice(0, 0, large), 0) == (
+ 200, '"1"', large)
+ assert request(source, 'GET', 'large') == (200, '"1"', large)
+ shown = subprocess.run([str(editor), '--store', str(store), 'show', 'large'],
+ capture_output=True, timeout=15)
+ assert shown.returncode == 0 and shown.stdout == large
+ payload = root / 'one-byte'
+ payload.write_bytes(b'Z')
+ edited = subprocess.run([str(editor), '--store', str(store), 'edit',
+ 'large', '1', '1048575', '1', str(payload)],
+ capture_output=True, timeout=15)
+ assert edited.returncode == 0, edited.stderr
+ assert request(fixed, 'GET', 'large') == (200, '"2"', large[:-1] + b'Z')
+ assert request(source, 'GET', 'large') == (200, '"2"', large[:-1] + b'Z')
+ fixed_after_large_rss = memory_kib(fixed.process.pid)
+ source_after_large_rss = memory_kib(source.process.pid)
+ fixed_peak_rss = memory_kib(fixed.process.pid, 'VmHWM:')
+ source_peak_rss = memory_kib(source.process.pid, 'VmHWM:')
+ assert fixed_peak_rss <= PEAK_RSS_LIMIT_KIB, (
+ fixed_peak_rss, PEAK_RSS_LIMIT_KIB)
+ finally:
+ fixed_stats = fixed.close()
+ source_stats = source.close()
+
+ limited = Host(fixed_binary, store, True, budget=1_048_576, timeout_ms=60000)
+ try:
+ with socket.create_connection(('127.0.0.1', limited.port), timeout=15) as sock:
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 4096)
+ sock.sendall(b'GET /objects/large HTTP/1.1\r\nHost: localhost\r\n'
+ b'Content-Length: 0\r\n\r\n')
+ slow = http.client.HTTPResponse(sock)
+ slow.begin()
+ assert slow.status == 200 and slow.read(1) == b'A'
+ assert request(limited, 'GET', 'note')[0] == 503
+ assert slow.read() == b'A' * 1_048_574 + b'Z'
+ slow.close()
+ for _ in range(40):
+ if request(limited, 'GET', 'note') == (200, '"2"', b'hello Pure'):
+ break
+ time.sleep(0.05)
+ else:
+ raise AssertionError('borrowed output was not released after draining')
+ finally:
+ limited_stats = limited.close()
+ assert limited_stats['peak_retained_payload_bytes'] == 1_048_576
+ symbols = subprocess.run(['nm', '-g', str(fixed_binary)], capture_output=True,
+ text=True, check=True, timeout=15).stdout
+ assert 'pure_program_parse' not in symbols and 'pure_program_load' not in symbols
+ return {'profile': 'build-time-prepared-http-document-host',
+ 'fixed_source_cli_same_document': 'pass',
+ 'conditional_conflict_and_invalid_splice': 'pass',
+ 'one_mib_roundtrip_and_native_edit': 'pass',
+ 'slow_consumer_budget_and_release': 'pass',
+ 'runtime_parser_symbols_absent': 'pass',
+ 'fixed_stats': fixed_stats, 'source_stats': source_stats,
+ 'limited_stats': limited_stats,
+ 'fixed_idle_rss_kib': fixed_idle_rss,
+ 'source_idle_rss_kib': source_idle_rss,
+ 'fixed_after_large_rss_kib': fixed_after_large_rss,
+ 'source_after_large_rss_kib': source_after_large_rss,
+ 'fixed_peak_rss_kib': fixed_peak_rss,
+ 'source_peak_rss_kib': source_peak_rss,
+ 'fixed_peak_rss_limit_kib': PEAK_RSS_LIMIT_KIB,
+ 'fixed_sha256': hashlib.sha256(fixed_binary.read_bytes()).hexdigest(),
+ 'source_sha256': hashlib.sha256(source_binary.read_bytes()).hexdigest()}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--build', type=Path, default=HERE / 'build')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ result = check(args.build)
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_flat_export.py b/prototypes/connections/check_flat_export.py
new file mode 100644
index 0000000..8122ec6
--- /dev/null
+++ b/prototypes/connections/check_flat_export.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python3
+"""Exercise paged-to-flat export with real native document edits and restore."""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import subprocess
+import tempfile
+from unittest.mock import patch as mock_patch
+
+import export_flat_store
+from export_flat_store import export
+
+
+def run(binary, store, *args):
+ result = subprocess.run([str(binary), '--store', str(store), *map(str, args)],
+ capture_output=True, timeout=30)
+ if result.returncode:
+ raise AssertionError((result.args, result.returncode, result.stderr[-400:]))
+ return result
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--paged-editor', type=Path, required=True)
+ parser.add_argument('--flat-editor', type=Path, required=True)
+ parser.add_argument('--extra-documents', type=int, default=0)
+ parser.add_argument('--scratch-parent', type=Path)
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.extra_documents < 0 or (args.output and args.output.exists()):
+ parser.error('extra documents must be non-negative and evidence file must be new')
+ paged, flat = args.paged_editor.resolve(), args.flat_editor.resolve()
+ if args.scratch_parent:
+ args.scratch_parent.mkdir(parents=True, exist_ok=True)
+ with tempfile.TemporaryDirectory(prefix='pure-flat-export-',
+ dir=args.scratch_parent.resolve() if args.scratch_parent else None) as name:
+ root = Path(name)
+ source, destination = root / 'paged', root / 'flat'
+ bodies = {'empty': b'', 'small': b'X', 'boundary': b'A' * 16384,
+ 'large': b'B' * 16385, 'megabyte': b'C' * 1_048_576}
+ base_keys = tuple(bodies)
+ for index in range(args.extra_documents):
+ bodies[f'extra{index:06d}'] = bytes((index % 251,)) * 128
+ revisions = {key: 1 for key in bodies}
+ for key, body in bodies.items():
+ input_file = root / (key + '.input')
+ input_file.write_bytes(body)
+ created = run(paged, source, 'edit', key, 0, 0, 0, input_file)
+ assert json.loads(created.stdout)['revision'] == '1'
+ patch = root / 'patch'
+ patch.write_bytes(b'Z')
+ for edit in range(65):
+ changed = run(paged, source, 'edit', 'megabyte', edit + 1,
+ 1_048_575, 1, patch)
+ assert json.loads(changed.stdout)['revision'] == str(edit + 2)
+ bodies['megabyte'] = bodies['megabyte'][:-1] + b'Z'
+ revisions['megabyte'] = 66
+ before = {key: run(paged, source, 'show', key).stdout for key in bodies}
+ result = export(source, destination, paged, flat)
+ assert result['objects'] == len(bodies)
+ assert result['logical_bytes'] == sum(map(len, bodies.values()))
+ for key, body in bodies.items():
+ opened = run(flat, destination, 'show', key)
+ assert opened.stdout == before[key] == body
+ assert json.loads(opened.stderr)['revision'] == str(revisions[key])
+ changed = run(flat, destination, 'edit', 'megabyte', 66,
+ 1_048_575, 1, patch)
+ assert json.loads(changed.stdout)['revision'] == '67'
+ assert json.loads(run(paged, source, 'show', 'megabyte').stderr)['revision'] == '66'
+ # Observe a cooperating writer while the export holds its read lock.
+ make_stage = export_flat_store.tempfile.mkdtemp
+ def check_locked(*stage_args, **stage_kwargs):
+ attempted = subprocess.run([str(paged), '--store', str(source), 'edit',
+ 'small', '1', '0', '1', str(patch)],
+ capture_output=True, timeout=30)
+ assert attempted.returncode == 2
+ assert json.loads(attempted.stderr)['error'] == 'busy'
+ return make_stage(*stage_args, **stage_kwargs)
+ with mock_patch.object(export_flat_store.tempfile, 'mkdtemp',
+ side_effect=check_locked):
+ export(source, root / 'locked', paged, flat)
+ assert json.loads(run(paged, source, 'edit', 'small', 1, 0, 1, patch).stdout)['revision'] == '2'
+ real_show = export_flat_store.show
+ calls = 0
+ def fail_during_read(*show_args):
+ nonlocal calls
+ calls += 1
+ if calls == 3:
+ raise RuntimeError('injected export read failure')
+ return real_show(*show_args)
+ interrupted = root / 'interrupted'
+ try:
+ with mock_patch.object(export_flat_store, 'show', side_effect=fail_during_read):
+ export(source, interrupted, paged, flat)
+ except RuntimeError as error:
+ assert str(error) == 'injected export read failure'
+ else:
+ raise AssertionError('injected export failure was not reported')
+ assert not interrupted.exists() and not list(root.glob('.interrupted.export-*'))
+ try:
+ export(source, destination, paged, flat)
+ except ValueError:
+ pass
+ else:
+ raise AssertionError('existing destination was replaced')
+ (source / 'obj-rogue').symlink_to(root / 'patch')
+ rejected = root / 'rejected'
+ try:
+ export(source, rejected, paged, flat)
+ except RuntimeError:
+ pass
+ else:
+ raise AssertionError('symlink object was accepted')
+ assert not rejected.exists()
+ assert not list(root.glob('.rejected.export-*'))
+ result.update({'passed': True, 'extra_documents': args.extra_documents,
+ 'scratch_parent': str(args.scratch_parent.resolve()) if args.scratch_parent else None,
+ 'source_revisions': {key: revisions[key] for key in base_keys},
+ 'readback_sha256': {key: hashlib.sha256(body).hexdigest()
+ for key, body in bodies.items() if key in base_keys},
+ 'flat_edit_after_export': 'revision 67',
+ 'writer_busy_during_export_and_resumed_after': True,
+ 'partial_export_not_published': True,
+ 'existing_target_and_symlink_rejected': True})
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_idle_wakes.py b/prototypes/connections/check_idle_wakes.py
new file mode 100644
index 0000000..4f1e466
--- /dev/null
+++ b/prototypes/connections/check_idle_wakes.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python3
+"""Count real idle poll calls before/after deadline-driven HTTP sleeping."""
+import argparse
+import hashlib
+import json
+import os
+from pathlib import Path
+import re
+import select
+import signal
+import subprocess
+import tarfile
+import tempfile
+import time
+
+
+def observe(binary, seconds):
+ with tempfile.TemporaryDirectory(prefix='pure-idle-poll-') as name:
+ root = Path(name)
+ trace = root / 'poll.log'
+ tracer = subprocess.Popen(['strace', '-qq', '-e', 'trace=poll,ppoll', '-o',
+ str(trace), str(binary), '--store',
+ str(root / 'store'), '--port', '0'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ start_new_session=True)
+ try:
+ ready, _, _ = select.select([tracer.stdout], [], [], 10)
+ assert ready, 'HTTP host did not become ready under strace'
+ message = json.loads(tracer.stdout.readline())
+ assert message['port'] > 0
+ children = Path(f'/proc/{tracer.pid}/task/{tracer.pid}/children')
+ pids = children.read_text().split()
+ assert len(pids) == 1, pids
+ time.sleep(seconds)
+ os.kill(int(pids[0]), signal.SIGTERM)
+ _, error = tracer.communicate(timeout=10)
+ assert tracer.returncode == 0, (tracer.returncode, error[-1000:])
+ captured = trace.read_text()
+ calls = [line for line in captured.splitlines()
+ if line.startswith(('poll(', 'ppoll('))]
+ values = []
+ for line in calls:
+ if line.startswith('ppoll('):
+ if re.search(r'\],\s*\d+,\s*NULL,', line):
+ values.append(-1)
+ elif match := re.search(r'\{tv_sec=(\d+), tv_nsec=(\d+)\}', line):
+ values.append(int(match.group(1)) * 1000 +
+ int(match.group(2)) // 1_000_000)
+ elif match := re.search(r',\s*(-?\d+)\)\s+=', line):
+ values.append(int(match.group(1)))
+ return {'poll_calls': len(calls), 'timeout_values_ms': sorted(set(values)),
+ 'trace_excerpt': captured[:500],
+ 'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest()}
+ finally:
+ if tracer.poll() is None:
+ os.killpg(tracer.pid, signal.SIGTERM)
+ try:
+ tracer.communicate(timeout=5)
+ except subprocess.TimeoutExpired:
+ os.killpg(tracer.pid, signal.SIGKILL)
+ tracer.communicate(timeout=5)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--before', type=Path, required=True)
+ parser.add_argument('--after', type=Path, required=True)
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ seconds = 1.25
+ with tempfile.TemporaryDirectory(prefix='pure-idle-before-') as directory:
+ baseline = args.before.resolve()
+ if baseline.name.endswith('.tar.gz'):
+ with tarfile.open(baseline, 'r:gz') as archive:
+ body = archive.extractfile('pure-document/bin/pure-connections-fixed').read()
+ baseline = Path(directory) / 'pure-connections-fixed'
+ baseline.write_bytes(body)
+ baseline.chmod(0o755)
+ before = observe(baseline, seconds)
+ after = observe(args.after.resolve(), seconds)
+ assert before['poll_calls'] >= 10, before
+ assert after['poll_calls'] <= 2, after
+ assert -1 in after['timeout_values_ms'], after
+ result = {'profile': 'idle-http-host-poll-syscalls',
+ 'observation_seconds': seconds, 'before': before, 'after': after,
+ 'deadline_driven_idle_wait': 'pass'}
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_micro_memory.py b/prototypes/connections/check_micro_memory.py
new file mode 100644
index 0000000..95fad1a
--- /dev/null
+++ b/prototypes/connections/check_micro_memory.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python3
+"""Check whole-process RSS for the selected CLI document workload."""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import platform
+import subprocess
+import tempfile
+
+HERE = Path(__file__).resolve().parent
+
+
+def measure(helper, command):
+ result = subprocess.run([helper, *command], capture_output=True, text=True,
+ check=True, timeout=15)
+ sample = json.loads(result.stdout)
+ if sample['exit_code']:
+ raise AssertionError(f'workload failed: {command}: {sample}')
+ return sample
+
+
+def check(build, fixed=False, portable=False):
+ budget_path = HERE / 'memory-budget.json'
+ budget = json.loads(budget_path.read_text())
+ if not portable and (platform.system() != 'Linux' or platform.machine() != 'aarch64'):
+ raise RuntimeError('reviewed memory profile requires Linux AArch64')
+ binary = (build / ('pure-edit-fixed' if fixed else 'pure-edit')).resolve()
+ helper = (build / 'measure-peak-rss').resolve()
+ program = HERE / 'examples/editor.pure'
+ with tempfile.TemporaryDirectory(prefix='pure-micro-memory-') as name:
+ root = Path(name)
+ small, large = root / 'small', root / 'large'
+ small.write_bytes(b'A')
+ large.write_bytes(b'B' * 1_048_576)
+ store = root / 'store'
+ base = [binary]
+ if not fixed:
+ base += ['--program', program]
+ base += ['--store', store]
+ raw_samples = {
+ 'small_edit_rss_kib': measure(helper, [*base, 'edit', 'small', '0', '0', '0', small]),
+ 'one_mib_edit_rss_kib': measure(helper, [*base, 'edit', 'large', '0', '0', '0', large]),
+ 'one_mib_show_rss_kib': measure(helper, [*base, 'show', 'large']),
+ }
+ samples = {name: sample['max_rss_kib'] for name, sample in raw_samples.items()}
+ shown = subprocess.run([*map(str, base), 'show', 'large'],
+ capture_output=True, check=True, timeout=15)
+ if shown.stdout != large.read_bytes():
+ raise AssertionError('measured document was not stored correctly')
+ if portable:
+ replacement = root / 'replacement'
+ replacement.write_bytes(b'Z')
+ raw_samples['one_mib_splice_rss_kib'] = measure(
+ helper, [*base, 'edit', 'large', '1', '524288', '1', replacement])
+ samples['one_mib_splice_rss_kib'] = raw_samples['one_mib_splice_rss_kib']['max_rss_kib']
+ edited = subprocess.run([*map(str, base), 'show', 'large'],
+ capture_output=True, check=True, timeout=15)
+ expected = large.read_bytes()[:524288] + b'Z' + large.read_bytes()[524289:]
+ if edited.stdout != expected:
+ raise AssertionError('one-byte revision edit did not survive a new process')
+ failures = [] if portable else [f'{name}: {value} > {budget["max_" + name]}'
+ for name, value in samples.items() if value > budget['max_' + name]]
+ if portable:
+ scope = ('Child-process peak RSS for native CLI document creation, read and '
+ 'one-byte revision edit; includes libc and the selected program form, '
+ 'excludes filesystem cache, kernel buffers, TLS, GUI and other apps. '
+ 'No cross-platform memory ceiling is asserted.')
+ else:
+ scope = budget['scope']
+ if fixed:
+ scope = scope.replace('program parsing', 'the embedded prepared program')
+ return {'passed': not failures, 'failures': failures,
+ 'profile': 'portable-measurement-no-budget' if portable else budget['profile'],
+ 'variant': 'fixed-program' if fixed else 'source-program',
+ 'scope': scope, 'samples': samples,
+ 'raw_samples': raw_samples if portable else None,
+ 'budget_sha256': None if portable else hashlib.sha256(budget_path.read_bytes()).hexdigest(),
+ 'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest(),
+ 'binary_bytes': binary.stat().st_size,
+ 'platform': platform.platform()}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--build', type=Path, required=True)
+ parser.add_argument('--fixed', action='store_true',
+ help='measure the parser-free fixed-program editor')
+ parser.add_argument('--portable', action='store_true',
+ help='measure native document work without a Linux-specific RSS ceiling')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ result = check(args.build, args.fixed, args.portable)
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(output)
+ print(output, end='')
+ if not result['passed']:
+ raise SystemExit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_mirror.py b/prototypes/connections/check_mirror.py
new file mode 100644
index 0000000..ed46fa8
--- /dev/null
+++ b/prototypes/connections/check_mirror.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+"""Run a real document through multiple in-process Pure domains and stores."""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import subprocess
+import tempfile
+
+
+def run(*args, code=0):
+ result = subprocess.run([str(arg) for arg in args], capture_output=True, timeout=30)
+ if result.returncode != code:
+ raise AssertionError((result.args, result.returncode, code, result.stderr[-500:]))
+ return result
+
+
+def edit(binary, store, key, revision, offset, remove, file):
+ result = run(binary, '--store', store, 'edit', key, revision, offset, remove, file)
+ return json.loads(result.stdout)['revision']
+
+
+def show(binary, store, key, revision, body):
+ result = run(binary, '--store', store, 'show', key)
+ assert result.stdout == body
+ assert json.loads(result.stderr)['revision'] == str(revision)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--mirror', type=Path, required=True)
+ parser.add_argument('--editor', type=Path, required=True)
+ parser.add_argument('--rss-helper', type=Path)
+ parser.add_argument('--scratch-parent', type=Path)
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ mirror, editor = args.mirror.resolve(), args.editor.resolve()
+ if args.scratch_parent:
+ args.scratch_parent.mkdir(parents=True, exist_ok=True)
+ with tempfile.TemporaryDirectory(prefix='pure-mirror-',
+ dir=args.scratch_parent.resolve() if args.scratch_parent else None) as name:
+ root = Path(name)
+ source, left, right = root / 'source', root / 'left', root / 'right'
+ initial = b'A' * 1_048_576
+ changed = initial[:-1] + b'Z'
+ input_file, patch, empty = root / 'initial', root / 'patch', root / 'empty'
+ input_file.write_bytes(initial)
+ patch.write_bytes(b'Z')
+ empty.write_bytes(b'')
+ assert edit(editor, source, 'document', 0, 0, 0, input_file) == '1'
+ first = json.loads(run(mirror, source, 'document', left, 'document', 0,
+ right, 'document', 0).stdout)
+ assert first['source_revision'] == '1' and first['bytes'] == len(initial)
+ assert [target['status'] for target in first['targets']] == ['ok', 'ok']
+ show(editor, left, 'document', 1, initial)
+ show(editor, right, 'document', 1, initial)
+
+ assert edit(editor, source, 'document', 1, len(initial) - 1, 1, patch) == '2'
+ show(editor, right, 'document', 1, initial)
+ partial = json.loads(run(mirror, source, 'document', left, 'document', 1,
+ right, 'document', 0, code=3).stdout)
+ assert [target['status'] for target in partial['targets']] == ['ok', 'conflict']
+ show(editor, left, 'document', 2, changed)
+ show(editor, right, 'document', 1, initial)
+ recovered = json.loads(run(mirror, source, 'document', right, 'document', 1).stdout)
+ assert recovered['targets'][0]['revision'] == '2'
+ show(editor, right, 'document', 2, changed)
+
+ assert edit(editor, source, 'empty', 0, 0, 0, empty) == '1'
+ assert json.loads(run(mirror, source, 'empty', left, 'empty', 0).stdout)['bytes'] == 0
+ show(editor, left, 'empty', 1, b'')
+ zero_budget = root / 'zero-budget'
+ assert json.loads(run(mirror, '--target-budget', 0, source, 'empty',
+ zero_budget, 'empty', 0).stdout)['targets'][0]['status'] == 'ok'
+ show(editor, zero_budget, 'empty', 1, b'')
+ low_budget = root / 'low-budget'
+ refused = json.loads(run(mirror, '--target-budget', 1024, source,
+ 'document', low_budget, 'document', 0, code=2).stdout)
+ assert refused == {'admission_status': 'budget', 'target_index': 0}
+ assert not list(low_budget.glob('obj-*'))
+
+ rejected_store = root / 'rejected'
+ rejected = json.loads(run(mirror, source, 'document', rejected_store,
+ 'document', 0, right, 'bad/key', 0, code=2).stdout)
+ assert rejected == {'admission_status': 'invalid', 'target_index': 1}
+ assert not list(rejected_store.glob('obj-*'))
+ show(editor, right, 'document', 2, changed)
+ missing_store = root / 'missing-target'
+ missing = json.loads(run(mirror, source, 'absent', missing_store,
+ 'document', 0, code=2).stdout)
+ assert missing == {'source_status': 'not_found'} and not missing_store.exists()
+
+ measured = None
+ fanout = [root / f'fanout-{index}' for index in range(8)]
+ fanout_args = [item for store in fanout for item in (store, 'document', 0)]
+ if args.rss_helper:
+ third, fourth = root / 'third', root / 'fourth'
+ measured = json.loads(run(args.rss_helper.resolve(), mirror, source,
+ 'document', third, 'document', 0,
+ fourth, 'document', 0).stdout)
+ assert measured['exit_code'] == 0
+ show(editor, third, 'document', 1, changed)
+ show(editor, fourth, 'document', 1, changed)
+ fanout_rss = json.loads(run(args.rss_helper.resolve(), mirror, source,
+ 'document', *fanout_args).stdout)
+ assert fanout_rss['exit_code'] == 0
+ else:
+ fanout_result = json.loads(run(mirror, source, 'document', *fanout_args).stdout)
+ assert len(fanout_result['targets']) == 8
+ assert all(target['status'] == 'ok' for target in fanout_result['targets'])
+ fanout_rss = None
+ for store in fanout:
+ show(editor, store, 'document', 1, changed)
+ result = {'passed': True, 'source_body_sha256': hashlib.sha256(changed).hexdigest(),
+ 'mirror_sha256': hashlib.sha256(mirror.read_bytes()).hexdigest(),
+ 'editor_sha256': hashlib.sha256(editor.read_bytes()).hexdigest(),
+ 'source_one_mib_to_two_domains': first,
+ 'independent_partial_conflict': partial,
+ 'conflict_recovered_revision': recovered['targets'][0]['revision'],
+ 'empty_body_forwarded': True,
+ 'target_budget_checked_before_document_write': True,
+ 'all_admissions_before_document_writes': True,
+ 'source_failure_before_target_creation': True,
+ 'one_mib_two_target_peak_rss': measured,
+ 'one_mib_eight_targets_verified': True,
+ 'one_mib_eight_target_peak_rss': fanout_rss}
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_package.py b/prototypes/connections/check_package.py
new file mode 100644
index 0000000..84adc05
--- /dev/null
+++ b/prototypes/connections/check_package.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python3
+"""Extract a binary preview elsewhere and run its real document paths."""
+import argparse
+import hashlib
+import http.client
+import json
+from pathlib import Path
+import select
+import subprocess
+import struct
+import tarfile
+import tempfile
+
+HERE = Path(__file__).resolve().parent
+
+
+def run(*args):
+ result = subprocess.run([str(arg) for arg in args], capture_output=True, timeout=90)
+ if result.returncode:
+ raise AssertionError((result.args, result.returncode, result.stdout[-1000:], result.stderr[-1000:]))
+ return result
+
+
+def check_http(server_binary, binary, program, root):
+ store = root / 'http-store'
+ insert = root / 'http-insert'
+ insert.write_bytes(b'hello Pure')
+ program_args = [] if program is None else ['--program', program]
+ run(binary, *program_args, '--store', store,
+ 'edit', 'note', '0', '0', '0', insert)
+ server = subprocess.Popen([str(server_binary), *map(str, program_args),
+ '--store', str(store), '--port', '0'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ try:
+ ready, _, _ = select.select([server.stdout], [], [], 5)
+ assert ready, 'packaged HTTP host did not start'
+ port = json.loads(server.stdout.readline())['port']
+ connection = http.client.HTTPConnection('127.0.0.1', port, timeout=5)
+ try:
+ body = struct.pack('<II', 10, 0) + b'!'
+ connection.request('PUT', '/objects/note', body,
+ {'Content-Length': str(len(body)), 'If-Match': '"1"'})
+ reply = connection.getresponse()
+ assert reply.status == 200 and reply.getheader('ETag') == '"2"'
+ assert reply.read() == b'!'
+ finally:
+ connection.close()
+ shown = run(binary, *program_args, '--store', store, 'show', 'note')
+ assert shown.stdout == b'hello Pure!'
+ finally:
+ server.terminate()
+ try:
+ server.communicate(timeout=5)
+ except subprocess.TimeoutExpired:
+ server.kill()
+ server.communicate(timeout=5)
+
+
+def check(archive):
+ archive = archive.resolve()
+ digest = hashlib.sha256(archive.read_bytes()).hexdigest()
+ checks = []
+ with tempfile.TemporaryDirectory(prefix='pure-preview-extracted-') as directory:
+ root = Path(directory)
+ with tarfile.open(archive, 'r:gz') as bundle:
+ members = bundle.getmembers()
+ assert all(item.isfile() and item.name.startswith('pure-document/') and
+ '..' not in Path(item.name).parts for item in members)
+ bundle.extractall(root, filter='data')
+ package = root / 'pure-document'
+ manifest = json.loads((package / 'manifest.json').read_text())
+ assert manifest['format'] == 'pure-document-preview-1'
+ package_budget = manifest.get('reviewed_package_budget')
+ if package_budget:
+ assert archive.stat().st_size <= package_budget['max_archive_bytes']
+ expected = {'pure-document/' + name for name in manifest['files']}
+ assert {item.name for item in members} == expected | {'pure-document/manifest.json'}
+ for name, metadata in manifest['files'].items():
+ content = (package / name).read_bytes()
+ assert len(content) == metadata['bytes']
+ assert hashlib.sha256(content).hexdigest() == metadata['sha256']
+ checks.append('relocated archive has only declared files and every file hash matches')
+
+ if manifest.get('program_mode') == 'build-time-prepared':
+ assert manifest['selected_hosts'][0] == 'pure-edit-fixed'
+ assert set(manifest['selected_hosts']) <= {
+ 'pure-edit-fixed', 'pure-connections-fixed', 'pure-edit-tui-fixed'}
+ assert 'share/editor.pure' not in manifest['files']
+ binary = package / 'bin/pure-edit-fixed'
+ store = root / 'fixed-store'
+ insert = root / 'fixed-insert'
+ insert.write_bytes(b'hello Pure')
+ written = run(binary, '--store', store, 'edit', 'note', '0', '0', '0', insert)
+ assert json.loads(written.stdout) == {'revision': '1', 'reply_bytes': 10}
+ assert (store / 'obj-note').read_bytes()[:8] == b'PUREB001'
+ assert run(binary, '--store', store, 'show', 'note').stdout == b'hello Pure'
+ checks.append('relocated parser-free runner creates and restores a document')
+ insert.write_bytes(b'!')
+ run(binary, '--store', store, 'edit', 'note', '1', '10', '0', insert)
+ assert run(binary, '--store', store, 'show', 'note').stdout == b'hello Pure!'
+ checks.append('relocated parser-free runner performs revision-checked edits')
+ if 'pure-connections-fixed' in manifest['selected_hosts']:
+ check_http(package / 'bin/pure-connections-fixed', binary, None, root)
+ checks.append('relocated parser-free HTTP host and CLI share the document')
+ if 'pure-edit-tui-fixed' in manifest['selected_hosts']:
+ tui = json.loads(run('python3', HERE / 'check_tui.py', '--build',
+ package / 'bin').stdout)
+ assert len(tui['checks']) >= 7
+ checks.append('relocated terminal editor saves UTF-8 and one MiB documents')
+ return {'archive_sha256': digest, 'archive_bytes': archive.stat().st_size,
+ 'selected_hosts': manifest['selected_hosts'], 'checks': checks}
+
+ binary = package / 'bin/pure-edit'
+ program = package / 'share/editor.pure'
+ store = root / 'store'
+ insert = root / 'insert.bin'
+ insert.write_bytes(b'hello Pure')
+ written = run(binary, '--program', program, '--store', store,
+ 'edit', 'note', '0', '0', '0', insert)
+ assert json.loads(written.stdout) == {'revision': '1', 'reply_bytes': 10}
+ profile = manifest.get('storage_profile')
+ expected_magic = b'PUREP001' if profile == 'PUREP001-16k-page-research' else b'PUREB001'
+ assert (store / 'obj-note').read_bytes()[:8] == expected_magic
+ shown = run(binary, '--program', program, '--store', store, 'show', 'note')
+ assert shown.stdout == b'hello Pure'
+ checks.append('extracted native CLI creates and restores the real document')
+ if profile == 'PUREB001+PUREP001-hybrid-16k-research':
+ big = root / 'big.bin'
+ big.write_bytes(b'X' * (16 * 1024 + 1))
+ run(binary, '--program', program, '--store', store,
+ 'edit', 'big', '0', '0', '0', big)
+ assert (store / 'obj-big').read_bytes()[:8] == b'PUREP001'
+ assert run(binary, '--program', program, '--store', store,
+ 'show', 'big').stdout == big.read_bytes()
+ checks.append('selected storage keeps small values inline and maps large values')
+
+ changed = root / 'changed.pure'
+ source = program.read_text()
+ assert 'reply(saved, edit.insert);' in source
+ changed.write_text(source.replace('reply(saved, edit.insert);', 'reply(saved);'))
+ changed_store = root / 'changed-store'
+ changed_result = run(binary, '--program', changed, '--store', changed_store,
+ 'edit', 'note', '0', '0', '0', insert)
+ assert json.loads(changed_result.stdout) == {'revision': '1', 'reply_bytes': 0}
+ checks.append('editing the packaged .pure source changes the executed reply')
+
+ if 'pure-connections' in manifest['selected_hosts']:
+ check_http(package / 'bin/pure-connections', binary, program, root)
+ checks.append('extracted HTTP host updates the same document as the native CLI')
+
+ if 'pure-edit-tui' in manifest['selected_hosts']:
+ tui = json.loads(run('python3', HERE / 'check_tui.py', '--build',
+ package / 'bin', '--source', '--program', program).stdout)
+ assert 'source CLI and TUI read the same document' in tui['checks']
+ checks.append('relocated source-loaded TUI and CLI share UTF-8, large and many-document paths')
+
+ peer = None
+ assert not ({'pure-document-peer', 'pure-document-server'} <=
+ set(manifest['selected_hosts']))
+ if 'pure-document-peer' in manifest['selected_hosts']:
+ peer = json.loads(run('python3', HERE / 'check_document_peer.py', '--peer',
+ package / 'bin/pure-document-peer', '--editor', binary,
+ '--program', program).stdout)
+ assert len(peer['checks']) >= 9
+ checks.append('extracted C/Python TLS peers share a 1 MiB document and recover')
+ if 'pure-document-server' in manifest['selected_hosts']:
+ peer = json.loads(run('python3', HERE / 'check_document_server_package.py',
+ '--server', package / 'bin/pure-document-server',
+ '--editor', binary, '--program', program).stdout)
+ assert len(peer['checks']) >= 5
+ checks.append('extracted server-only TLS peer and external client share a 1 MiB document and recover')
+ if 'pure-edit-window' in manifest['selected_hosts']:
+ key_switch = 'native-document-key-switch' in manifest.get('features', [])
+ window = json.loads(run('xvfb-run', '-a', '-s', '-screen 0 1280x800x24',
+ 'python3', HERE / 'check_window.py', '--build',
+ package / 'bin', '--program', program,
+ *([] if key_switch else ['--legacy-window'])).stdout)
+ assert window['one_mib_document_one_byte_edit'] == 'pass'
+ if key_switch:
+ assert window['multi_document_switch_preserves_draft'] == 'pass'
+ checks.append('extracted GTK window switches documents without losing drafts')
+ else:
+ checks.append('extracted archived GTK window edits the same document')
+ result = {'archive_sha256': digest, 'archive_bytes': archive.stat().st_size,
+ 'selected_hosts': manifest['selected_hosts'], 'checks': checks}
+ if peer is not None:
+ result['peer_checks'] = peer['checks']
+ result['peer_idle_rss_kib'] = peer['server_idle_rss_kib']
+ result['peer_after_large_work_rss_kib'] = peer['server_after_large_work_rss_kib']
+ return result
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('archive', type=Path)
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ result = check(args.archive)
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_policy.py b/prototypes/connections/check_policy.py
new file mode 100644
index 0000000..5fce560
--- /dev/null
+++ b/prototypes/connections/check_policy.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python3
+"""Exercise an authored final-size guard through native source and fixed apps."""
+import argparse
+import http.client
+import json
+from pathlib import Path
+import select
+import struct
+import subprocess
+import tempfile
+from check_tui import Terminal
+from check_document_peer import (certificates, connect, edit as peer_edit,
+ hello, request as peer_request, start, stop)
+
+
+def run(binary, program, store, *args):
+ command = [str(binary)]
+ if program is not None:
+ command += ['--program', str(program)]
+ command += ['--store', str(store), *map(str, args)]
+ return subprocess.run(command, capture_output=True, timeout=15)
+
+
+def edit(binary, program, store, payload, key, revision, offset, remove, body):
+ payload.write_bytes(body)
+ return run(binary, program, store, 'edit', key, revision, offset, remove, payload)
+
+
+def result(process, status, revision):
+ assert process.returncode == status, (process.returncode, process.stderr)
+ channel = process.stdout if status == 0 else process.stderr
+ value = json.loads(channel)
+ assert value['revision'] == str(revision), value
+ if status:
+ assert value['error'] == 'limit' if status == 2 else value['error'] == 'conflict'
+
+
+def body(binary, program, store, expected):
+ shown = run(binary, program, store, 'show', 'note')
+ assert shown.returncode == 0 and shown.stdout == expected
+ return int(json.loads(shown.stderr)['revision'])
+
+
+class Server:
+ def __init__(self, binary, program, store):
+ command = [str(binary), '--store', str(store), '--port', '0']
+ if program is not None:
+ command += ['--program', str(program)]
+ self.process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ ready, _, _ = select.select([self.process.stdout], [], [], 10)
+ if not ready:
+ self.process.kill()
+ raise AssertionError('document server did not start')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.port = json.loads(line)['port']
+
+ def request(self, method, data=b'', expected=None):
+ headers = {'Content-Length': str(len(data))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = (
+ '*' if expected == 0 else f'"{expected}"')
+ connection = http.client.HTTPConnection('127.0.0.1', self.port, timeout=15)
+ try:
+ connection.request(method, '/objects/note', data, headers)
+ response = connection.getresponse()
+ return response.status, response.getheader('ETag'), response.read()
+ finally:
+ connection.close()
+
+ def close(self):
+ self.process.terminate()
+ _, error = self.process.communicate(timeout=10)
+ assert self.process.returncode == 0, error[-1000:]
+ stats = json.loads(error)
+ assert stats['active'] == stats['retained_payload_bytes'] == 0
+
+
+def splice(offset, remove, insert):
+ return struct.pack('<II', offset, remove) + insert
+
+
+def scenario(binary, program, directory):
+ directory.mkdir()
+ store = directory / 'store'
+ payload = directory / 'insert'
+ result(edit(binary, program, store, payload, 'note', 0, 0, 0, b'abcdef'), 0, 1)
+ result(edit(binary, program, store, payload, 'note', 1, 6, 0, b'gh'), 0, 2)
+ result(edit(binary, program, store, payload, 'note', 2, 8, 0, b'i'), 2, 2)
+ assert body(binary, program, store, b'abcdefgh') == 2
+ result(edit(binary, program, store, payload, 'note', 1, 7, 1, b'Z'), 3, 2)
+ result(edit(binary, program, store, payload, 'note', 2, 7, 1, b'Z'), 0, 3)
+ assert body(binary, program, store, b'abcdefgZ') == 3
+ return store, payload
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--source', type=Path, required=True)
+ parser.add_argument('--fixed', type=Path, required=True)
+ parser.add_argument('--source-server', type=Path, required=True)
+ parser.add_argument('--fixed-server', type=Path, required=True)
+ parser.add_argument('--source-tui', type=Path, required=True)
+ parser.add_argument('--fixed-tui', type=Path, required=True)
+ parser.add_argument('--definition', type=Path, required=True)
+ parser.add_argument('--peer', type=Path)
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ definition = args.definition.read_text()
+ assert definition.count('edit.insert, 8)') == 1
+ with tempfile.TemporaryDirectory(prefix='pure-authored-policy-') as temp:
+ root = Path(temp)
+ authored = root / 'policy.pure'
+ authored.write_text(definition)
+ source_store, payload = scenario(args.source, authored, root / 'source')
+ fixed_store, _ = scenario(args.fixed, None, root / 'fixed')
+ source_http = Server(args.source_server, authored, source_store)
+ try:
+ assert source_http.request('GET') == (200, '"3"', b'abcdefgZ')
+ assert source_http.request('PUT', splice(8, 0, b'i'), 3)[0] == 413
+ assert source_http.request('GET') == (200, '"3"', b'abcdefgZ')
+ finally:
+ source_http.close()
+ authored.write_text(definition.replace('edit.insert, 8)', 'edit.insert, 4)'))
+ result(edit(args.source, authored, source_store, payload, 'note', 3, 7, 1, b'Y'), 2, 3)
+ assert body(args.source, authored, source_store, b'abcdefgZ') == 3
+ source_http = Server(args.source_server, authored, source_store)
+ try:
+ assert source_http.request('PUT', splice(4, 4, b''), 3) == (200, '"4"', b'')
+ finally:
+ source_http.close()
+ assert body(args.source, authored, source_store, b'abcd') == 4
+ result(edit(args.source, authored, source_store, payload, 'note', 4, 4, 0, b'X'), 2, 4)
+ assert body(args.source, authored, source_store, b'abcd') == 4
+ source_tui = Terminal(args.source_tui, authored, source_store, 'note')
+ try:
+ source_tui.type(b'X\x13')
+ source_tui.wait_for(b'Save failed: document limit')
+ assert body(args.source, authored, source_store, b'abcd') == 4
+ finally:
+ source_tui.close(discard=True)
+ if args.peer:
+ tls = root / 'tls'
+ tls.mkdir()
+ ca = certificates(tls)
+ process, port = start(args.peer, authored, source_store, tls, ca)
+ try:
+ with connect(tls, ca, port) as socket:
+ hello(socket, authored)
+ assert peer_request(socket, 2, 'note', 4, peer_edit(4, 0, b'X')) == (5, 4, b'', 0)
+ assert peer_request(socket, 1, 'note') == (0, 4, b'abcd', 4)
+ assert peer_request(socket, 2, 'note', 4, peer_edit(3, 1, b'')) == (0, 5, b'', 0)
+ assert peer_request(socket, 1, 'note') == (0, 5, b'abc', 3)
+ finally:
+ stop(process)
+ assert body(args.source, authored, source_store, b'abc') == 5
+ # The compiled definition retains its original policy after source edits.
+ fixed_http = Server(args.fixed_server, None, fixed_store)
+ try:
+ assert fixed_http.request('PUT', splice(7, 1, b'Y'), 3) == (200, '"4"', b'Y')
+ finally:
+ fixed_http.close()
+ assert body(args.fixed, None, fixed_store, b'abcdefgY') == 4
+ fixed_tui = Terminal(args.fixed_tui, None, fixed_store, 'note')
+ try:
+ fixed_tui.type(b'X\x13')
+ fixed_tui.wait_for(b'Save failed: document limit')
+ assert body(args.fixed, None, fixed_store, b'abcdefgY') == 4
+ finally:
+ fixed_tui.close(discard=True)
+ evidence = {'checks': [
+ 'authored final size is checked against the locked document version',
+ 'a rejected growth leaves revision and bytes unchanged',
+ 'stale revision reports conflict before the policy decision',
+ 'source CLI and HTTP share a policy and committed document',
+ 'source policy changes behavior after the HTTP host restarts',
+ 'fixed CLI and HTTP retain their compiled policy after source edits',
+ 'source and fixed terminal editors preserve unsaved drafts on policy denial']}
+ if args.peer:
+ evidence['checks'].append('authenticated peer shares the policy and current stored version')
+ if args.output:
+ args.output.write_text(json.dumps(evidence, indent=2) + '\n')
+ print(json.dumps(evidence))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_profile.py b/prototypes/connections/check_profile.py
new file mode 100644
index 0000000..ac2ba00
--- /dev/null
+++ b/prototypes/connections/check_profile.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+"""Check the selected default hosts' linked code and direct dependencies.
+
+This is a Linux/GNU release-build gate, separate from sanitizer and core checks.
+It does not estimate process RAM or the cost of optional UI/network hosts.
+"""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import platform
+import re
+import subprocess
+
+ROOT = Path(__file__).resolve().parent
+NEEDED = re.compile(r"\(NEEDED\).*Shared library: \[([^]]+)\]")
+
+
+def run(*args):
+ return subprocess.check_output([str(arg) for arg in args], text=True)
+
+
+def inspect(path):
+ rows = [row.split() for row in run('size', path).splitlines()]
+ if len(rows) != 2 or len(rows[1]) < 6 or not all(
+ rows[1][i].isdigit() for i in range(3)):
+ raise ValueError(f'unsupported size output for {path}')
+ sections = dict(zip(('text', 'data', 'bss'), map(int, rows[1][:3])))
+ needed = sorted(NEEDED.findall(run('readelf', '-d', path)))
+ return {'sections': sections, 'needed': needed,
+ 'sha256': hashlib.sha256(path.read_bytes()).hexdigest()}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--build', type=Path, required=True)
+ parser.add_argument('--budget', type=Path, default=ROOT / 'profile-budget.json')
+ parser.add_argument('--only', action='append', metavar='BINARY',
+ help='check only this selected binary (repeatable)')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ budget = json.loads(args.budget.read_text())
+ selected = args.only or list(budget['binaries'])
+ unknown = set(selected) - set(budget['binaries'])
+ if unknown:
+ parser.error(f'unknown budget binary: {sorted(unknown)}')
+ binaries = {}
+ failures = []
+ for name in selected:
+ limits = budget['binaries'][name]
+ path = args.build / name
+ try:
+ observed = inspect(path)
+ except (OSError, subprocess.CalledProcessError, ValueError) as error:
+ failures.append(f'{name}: cannot inspect: {error}')
+ continue
+ binaries[name] = observed
+ for section, value in observed['sections'].items():
+ limit = limits[f'max_{section}_bytes']
+ if value > limit:
+ failures.append(f'{name} {section}: {value} > {limit}')
+ if observed['needed'] != sorted(limits['needed']):
+ failures.append(f'{name} dependencies: {observed["needed"]} '
+ f'!= {sorted(limits["needed"])}')
+ result = {'passed': not failures, 'failures': failures,
+ 'profile': budget['profile'], 'scope': budget['scope'],
+ 'budget_sha256': hashlib.sha256(args.budget.read_bytes()).hexdigest(),
+ 'platform': platform.platform(), 'binaries': binaries}
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+ if failures:
+ raise SystemExit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_service_scale.py b/prototypes/connections/check_service_scale.py
new file mode 100644
index 0000000..fb04baf
--- /dev/null
+++ b/prototypes/connections/check_service_scale.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+"""Exercise the real document app across many objects and concurrent clients."""
+import argparse
+from concurrent.futures import ThreadPoolExecutor
+import hashlib
+import json
+from pathlib import Path
+import subprocess
+import tempfile
+
+from check_fixed_server import Host, memory_kib, request, splice
+
+HERE = Path(__file__).resolve().parent
+DOCUMENTS = 1024
+CLIENTS = 8
+BODY_BYTES = 8192
+SERVER_BUDGET = 1_048_576
+PEAK_RSS_LIMIT_KIB = 4096
+
+
+def document(index):
+ seed = f'document:{index:04d}:'.encode()
+ return (seed * ((BODY_BYTES + len(seed) - 1) // len(seed)))[:BODY_BYTES]
+
+
+def client(host, client_number):
+ digests = []
+ for index in range(client_number, DOCUMENTS, CLIENTS):
+ key = f'doc{index:04d}'
+ original = document(index)
+ created = request(host, 'PUT', key, splice(0, 0, original), 0)
+ assert created == (200, '"1"', original), (index, 'create', created[:2])
+ opened = request(host, 'GET', key)
+ assert opened == (200, '"1"', original), (index, 'open', opened[:2])
+ replacement = bytes((65 + index % 26,))
+ edited = request(host, 'PUT', key,
+ splice(BODY_BYTES - 1, 1, replacement), 1)
+ assert edited == (200, '"2"', replacement), (index, 'edit', edited[:2])
+ final = original[:-1] + replacement
+ restored = request(host, 'GET', key)
+ assert restored == (200, '"2"', final), (index, 'restore', restored[:2])
+ digests.append((index, hashlib.sha256(final).digest()))
+ return digests
+
+
+def run_variant(build, root, fixed, async_source=False):
+ assert not (fixed and async_source)
+ store = root / ('fixed' if fixed else 'source-async' if async_source else 'source')
+ binary = build / ('pure-connections-fixed' if fixed else
+ 'pure-connections-async' if async_source else 'pure-connections')
+ host = Host(binary, store, fixed, budget=SERVER_BUDGET)
+ idle_rss = memory_kib(host.process.pid)
+ idle_vm = memory_kib(host.process.pid, 'VmSize:')
+ idle_threads = memory_kib(host.process.pid, 'Threads:')
+ try:
+ with ThreadPoolExecutor(max_workers=CLIENTS) as pool:
+ batches = list(pool.map(lambda number: client(host, number),
+ range(CLIENTS)))
+ all_digests = sorted(item for batch in batches for item in batch)
+ assert len(all_digests) == DOCUMENTS
+ digest = hashlib.sha256(b''.join(value for _, value in all_digests)).hexdigest()
+ peak_rss = memory_kib(host.process.pid, 'VmHWM:')
+ peak_vm = memory_kib(host.process.pid, 'VmPeak:')
+ peak_threads = memory_kib(host.process.pid, 'Threads:')
+ finally:
+ stats = host.close()
+ editor = build / ('pure-edit-fixed' if fixed else 'pure-edit')
+ for index in (0, 127, 512, DOCUMENTS - 1):
+ key = f'doc{index:04d}'
+ args = [str(editor), '--store', str(store)]
+ if not fixed:
+ args += ['--program', str(HERE / 'examples/editor.pure')]
+ shown = subprocess.run([*args, 'show', key], capture_output=True, timeout=15)
+ replacement = bytes((65 + index % 26,))
+ assert shown.returncode == 0, (index, shown.stderr)
+ assert shown.stdout == document(index)[:-1] + replacement, index
+ assert json.loads(shown.stderr)['revision'] == '2', index
+ objects = list(store.glob('obj-*'))
+ assert len(objects) == DOCUMENTS, len(objects)
+ assert stats['accepted'] == DOCUMENTS * 4, stats
+ assert stats['commits'] == DOCUMENTS * 2, stats
+ assert stats['gets'] == DOCUMENTS * 2, stats
+ assert stats['releases'] == DOCUMENTS * 4, stats
+ assert stats['budget_rejections'] == stats['expired'] == 0, stats
+ assert stats['peak_connections'] <= CLIENTS, stats
+ assert stats['peak_retained_payload_bytes'] <= SERVER_BUDGET, stats
+ assert peak_rss <= PEAK_RSS_LIMIT_KIB, peak_rss
+ return {'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest(),
+ 'document_digest': digest, 'stored_objects': len(objects),
+ 'stored_file_bytes': sum(path.stat().st_size for path in objects),
+ 'fresh_cli_restore_samples': 4, 'idle_rss_kib': idle_rss,
+ 'peak_rss_kib': peak_rss, 'idle_vm_kib': idle_vm,
+ 'peak_vm_kib': peak_vm, 'idle_threads': idle_threads,
+ 'peak_threads': peak_threads, 'stats': stats}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--build', type=Path, default=HERE / 'build')
+ parser.add_argument('--output', type=Path)
+ parser.add_argument('--async-source', action='store_true',
+ help='also run the optional one-worker HTTP host')
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ build = args.build.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-document-scale-') as directory:
+ root = Path(directory)
+ fixed = run_variant(build, root, True)
+ source = run_variant(build, root, False)
+ async_source = run_variant(build, root, False, True) if args.async_source else None
+ assert fixed['document_digest'] == source['document_digest']
+ if async_source:
+ assert source['document_digest'] == async_source['document_digest']
+ result = {'profile': 'document-app-many-objects-concurrent-clients',
+ 'documents_per_variant': DOCUMENTS, 'clients': CLIENTS,
+ 'body_bytes': BODY_BYTES, 'operations_per_variant': DOCUMENTS * 4,
+ 'server_budget_bytes': SERVER_BUDGET,
+ 'peak_rss_limit_kib': PEAK_RSS_LIMIT_KIB,
+ 'same_final_documents': 'pass', 'fixed': fixed, 'source': source}
+ if async_source:
+ result['source_async'] = async_source
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_small_scan.py b/prototypes/connections/check_small_scan.py
new file mode 100644
index 0000000..e5f3223
--- /dev/null
+++ b/prototypes/connections/check_small_scan.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+"""Reject directory-wide segment scans on the selected small-object edit path."""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import subprocess
+import tempfile
+
+HERE = Path(__file__).resolve().parent
+
+
+def run(*args):
+ result = subprocess.run([str(value) for value in args], capture_output=True, timeout=20)
+ if result.returncode:
+ raise AssertionError((result.args, result.returncode, result.stderr[-500:]))
+ return result
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--editor', required=True, type=Path)
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ editor = args.editor.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-small-scan-') as name:
+ root = Path(name)
+ store = root / 'store'
+ one = root / 'one'
+ one.write_bytes(b'A')
+ base = (editor, '--program', HERE / 'examples/editor.pure', '--store', store)
+ run(*base, 'edit', 'tiny', 0, 0, 0, one)
+ for index in range(256):
+ (store / f'unrelated-{index:03d}').write_bytes(b'')
+ trace = root / 'trace'
+ run('strace', '-qq', '-e', 'getdents64', '-yy', '-o', trace,
+ *base, 'edit', 'tiny', 1, 0, 1, one)
+ scans = [line for line in trace.read_text().splitlines()
+ if 'getdents64(' in line and str(store) in line]
+ assert not scans, scans
+ result = {'small_edit_store_directory_scans': 0,
+ 'unrelated_directory_entries': 256,
+ 'binary_sha256': hashlib.sha256(editor.read_bytes()).hexdigest()}
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ if args.output.exists():
+ parser.error('evidence file already exists')
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_source_package.py b/prototypes/connections/check_source_package.py
new file mode 100644
index 0000000..5bc2f15
--- /dev/null
+++ b/prototypes/connections/check_source_package.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+"""Verify a source snapshot after safe extraction and a clean native build."""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import subprocess
+import tarfile
+import tempfile
+
+PREFIX = 'pure-source-preview/'
+
+
+def run(*args, timeout=120):
+ result = subprocess.run([str(arg) for arg in args], capture_output=True, timeout=timeout)
+ if result.returncode:
+ raise AssertionError((result.args, result.returncode,
+ result.stdout[-2000:], result.stderr[-2000:]))
+ return result
+
+
+def check(archive, release, peer, copy_range, flat_export, mirror, hybrid_tui):
+ archive = archive.resolve()
+ checks = []
+ with tempfile.TemporaryDirectory(prefix='pure-source-extracted-') as directory:
+ root = Path(directory)
+ package = root / PREFIX[:-1]
+ with tarfile.open(archive, 'r:gz') as bundle:
+ members = bundle.getmembers()
+ names = [member.name for member in members]
+ assert len(names) == len(set(names))
+ assert all(member.isfile() and member.name.startswith(PREFIX) and
+ '..' not in Path(member.name).parts for member in members)
+ for member in members:
+ destination = root / member.name
+ destination.parent.mkdir(parents=True, exist_ok=True)
+ destination.write_bytes(bundle.extractfile(member).read())
+ manifest = json.loads((package / 'manifest.json').read_text())
+ assert manifest['format'] == 'pure-source-preview-1'
+ assert set(names) == {PREFIX + name for name in manifest['files']} | {PREFIX + 'manifest.json'}
+ for name, metadata in manifest['files'].items():
+ content = (package / name).read_bytes()
+ assert len(content) == metadata['bytes']
+ assert hashlib.sha256(content).hexdigest() == metadata['sha256']
+ checks.append('every extracted source file matches the manifest')
+
+ connections = package / 'prototypes/connections'
+ run('make', '-C', connections, timeout=120)
+ default_outputs = {path.name for path in (connections / 'build').iterdir()}
+ assert default_outputs == {'runtime.o', 'libpure-execution.a',
+ 'pure-compile', 'embedded-plan.h',
+ 'pure-edit-fixed'}, default_outputs
+ checks.append('clean default build contains only the core, parser-free CLI and its build-time compiler')
+ run('make', '-C', connections, 'check-native-checkpoint', timeout=300)
+ checks.append('clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass')
+ run('make', '-C', connections, 'fixed-editor')
+ editor = connections / 'build/pure-edit'
+ fixed = connections / 'build/pure-edit-fixed'
+ program = connections / 'examples/editor.pure'
+ store = root / 'document-store'
+ insert = root / 'insert.bin'
+ insert.write_bytes(b'hello Pure')
+ written = run(editor, '--program', program, '--store', store,
+ 'edit', 'note', '0', '0', '0', insert)
+ assert json.loads(written.stdout) == {'revision': '1', 'reply_bytes': 10}
+ assert run(fixed, '--store', store, 'show', 'note').stdout == b'hello Pure'
+ checks.append('source-loaded CLI and parser-free CLI share the real stored document')
+
+ changed = root / 'changed.pure'
+ source = program.read_text()
+ assert 'reply(saved, edit.insert);' in source
+ changed.write_text(source.replace('reply(saved, edit.insert);', 'reply(saved);'))
+ changed_store = root / 'changed-store'
+ changed_result = run(editor, '--program', changed, '--store', changed_store,
+ 'edit', 'note', '0', '0', '0', insert)
+ assert json.loads(changed_result.stdout) == {'revision': '1', 'reply_bytes': 0}
+ checks.append('editing .pure changes the native source-loaded reply')
+
+ if peer:
+ run('make', '-C', connections, 'check-portable-peer', timeout=180)
+ checks.append('clean native TLS client and both server profiles pass authenticated document work')
+
+ if copy_range:
+ run('make', '-C', connections, 'check-copy-range', timeout=240)
+ checks.append('clean selected Linux copy path passes app, scale, size, RSS and traced one-MiB splice')
+
+ if flat_export:
+ run('make', '-C', connections, 'check-flat-export', timeout=180)
+ checks.append('clean selected page store exports mixed revisions to the default flat store')
+
+ if mirror:
+ run('make', '-C', connections, 'check-mirror', timeout=180)
+ checks.append('clean one-MiB document fans out to two same-process Pure domains with independent conflict and release')
+
+ if hybrid_tui:
+ run('make', '-C', connections, 'BUILD=build/hybrid', 'STORE=store-paged.c',
+ 'editor', 'source-tui', timeout=120)
+ run('python3', connections / 'check_tui.py', '--build',
+ connections / 'build/hybrid', '--source', timeout=120)
+ selected = root / 'hybrid-tui.tar.gz'
+ run('python3', connections / 'package_native.py', '--build',
+ connections / 'build/hybrid', '--hybrid-storage', '--with-tui',
+ '--output', selected, timeout=120)
+ run('python3', connections / 'check_package.py', selected, timeout=120)
+ checks.append('clean selected page store runs the source-loaded TUI and relocatable CLI+TUI package')
+
+ if release:
+ run('make', '-C', connections, 'check-release', timeout=180)
+ checks.append('clean Linux release behavior, code, dependency and RSS gates pass')
+ run('make', '-C', connections, 'check-source-tui', timeout=120)
+ checks.append('clean source-loaded terminal editor PTY scenarios pass')
+ return {'archive_sha256': hashlib.sha256(archive.read_bytes()).hexdigest(),
+ 'archive_bytes': archive.stat().st_size, 'source_files': len(manifest['files']),
+ 'checks': checks}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('archive', type=Path)
+ parser.add_argument('--release', action='store_true', help='also run Linux release gates')
+ parser.add_argument('--peer', action='store_true',
+ help='also build and exercise the optional TLS client and servers')
+ parser.add_argument('--copy-range', action='store_true',
+ help='also check the opt-in Linux file copy path with strace')
+ parser.add_argument('--flat-export', action='store_true',
+ help='also check selected paged-to-default document store export')
+ parser.add_argument('--mirror', action='store_true',
+ help='also check one-process document fan-out through two Pure domains')
+ parser.add_argument('--hybrid-tui', action='store_true',
+ help='also build and relocate the selected 16 KiB-page native terminal app')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ result = check(args.archive, args.release, args.peer, args.copy_range,
+ args.flat_export, args.mirror, args.hybrid_tui)
+ text = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(text)
+ print(text, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_tui.py b/prototypes/connections/check_tui.py
new file mode 100644
index 0000000..5328d02
--- /dev/null
+++ b/prototypes/connections/check_tui.py
@@ -0,0 +1,352 @@
+#!/usr/bin/env python3
+"""Exercise the real terminal editor through a PTY and the same document CLI."""
+import argparse
+import fcntl
+import hashlib
+import json
+import locale
+import os
+from pathlib import Path
+import pty
+import select
+import signal
+import struct
+import subprocess
+import tempfile
+import termios
+import time
+
+HERE = Path(__file__).resolve().parent
+
+
+def command(*args):
+ return subprocess.run([str(arg) for arg in args], capture_output=True,
+ timeout=20, check=True)
+
+
+def utf8_locale():
+ original = locale.setlocale(locale.LC_CTYPE)
+ candidates = [os.environ.get('LC_ALL'), os.environ.get('LC_CTYPE'),
+ os.environ.get('LANG'), 'C.UTF-8', 'en_US.UTF-8']
+ try:
+ for candidate in candidates:
+ if not candidate:
+ continue
+ try:
+ locale.setlocale(locale.LC_CTYPE, candidate)
+ except locale.Error:
+ continue
+ if locale.nl_langinfo(locale.CODESET).upper().replace('-', '') == 'UTF8':
+ return candidate
+ finally:
+ locale.setlocale(locale.LC_CTYPE, original)
+ raise AssertionError('no UTF-8 locale available for terminal test')
+
+
+def memory_kib(pid, field, portable=False):
+ if portable:
+ return None
+ for line in Path(f'/proc/{pid}/status').read_text().splitlines():
+ if line.startswith(field):
+ return int(line.split()[1])
+ raise AssertionError(field)
+
+
+class Terminal:
+ def __init__(self, binary, program, store, key):
+ self.master, self.slave = pty.openpty()
+ fcntl.ioctl(self.slave, termios.TIOCSWINSZ, struct.pack('HHHH', 24, 80, 0, 0))
+ self.original = termios.tcgetattr(self.slave)
+ language = utf8_locale()
+ self.process = subprocess.Popen([str(binary),
+ *(['--program', str(program)] if program else []),
+ '--store', str(store), key],
+ stdin=self.slave, stdout=self.slave, stderr=self.slave,
+ env={**os.environ, 'LANG': language,
+ 'LC_ALL': language})
+ self.wait_for(f'Pure | {key}'.encode())
+
+ def wait_for(self, marker, timeout=8):
+ seen = b''
+ deadline = time.monotonic() + timeout
+ while time.monotonic() < deadline:
+ ready, _, _ = select.select([self.master], [], [], 0.1)
+ if ready:
+ part = os.read(self.master, 65536)
+ seen = (seen + part)[-65536:]
+ if marker in seen:
+ return seen
+ if self.process.poll() is not None:
+ break
+ raise AssertionError((marker, self.process.poll(), seen[-2000:]))
+
+ def type(self, data):
+ os.write(self.master, data)
+
+ def resize(self, rows, columns):
+ fcntl.ioctl(self.slave, termios.TIOCSWINSZ,
+ struct.pack('HHHH', rows, columns, 0, 0))
+ os.kill(self.process.pid, signal.SIGWINCH)
+
+ def close(self, discard=False):
+ if self.process.poll() is None:
+ self.type(b'\x11')
+ if discard:
+ self.wait_for(b'Unsaved draft')
+ self.type(b'\x11')
+ self.process.wait(timeout=8)
+ assert self.process.returncode == 0, self.process.returncode
+ restored = termios.tcgetattr(self.slave)
+ assert restored == self.original, (restored, self.original)
+ os.close(self.master)
+ os.close(self.slave)
+
+ def signal_close(self):
+ os.kill(self.process.pid, signal.SIGTERM)
+ self.process.wait(timeout=8)
+ assert self.process.returncode == 0, self.process.returncode
+ assert termios.tcgetattr(self.slave) == self.original
+ os.close(self.master)
+ os.close(self.slave)
+
+
+def shown(editor, store, key):
+ result = command(*editor, '--store', store, 'show', key)
+ return result.stdout, json.loads(result.stderr)['revision']
+
+
+def wait_stored(editor, store, key, expected, revision):
+ deadline = time.monotonic() + 8
+ while time.monotonic() < deadline:
+ try:
+ body, found_revision = shown(editor, store, key)
+ if body == expected and found_revision == str(revision):
+ return
+ except subprocess.CalledProcessError:
+ pass
+ time.sleep(0.05)
+ raise AssertionError((key, expected[:100], shown(editor, store, key)))
+
+
+def check(build, rss_limit_kib, source, program_path, portable=False):
+ binary = (build / ('pure-edit-tui' if source else 'pure-edit-tui-fixed')).resolve()
+ program = (program_path or HERE / 'examples/editor.pure').resolve() if source else None
+ editor = [str((build / ('pure-edit' if source else 'pure-edit-fixed')).resolve())]
+ if source:
+ editor += ['--program', str(program)]
+ with tempfile.TemporaryDirectory(prefix='pure-tui-') as name:
+ root = Path(name)
+ store = root / 'store'
+ if source:
+ invalid = root / 'invalid.pure'
+ invalid.write_text('not a pure program\n')
+ for candidate, marker in ((invalid, b'Program:'),
+ (HERE / 'examples/storage.pure', b'Program needs')):
+ denied = subprocess.run([str(binary), '--program', str(candidate),
+ '--store', str(store), 'note'],
+ capture_output=True, timeout=10)
+ assert denied.returncode == 2 and marker in denied.stderr
+ assert not store.exists()
+ terminal = Terminal(binary, program, store, 'note')
+ try:
+ terminal.type(b'hello Pure\x1b[D\x1b[D!\x13')
+ wait_stored(editor, store, 'note', b'hello Pu!re', 1)
+ if source:
+ assert command(*editor, '--store', store, 'show', 'note').stdout == b'hello Pu!re'
+ terminal.type(b'\x0fsecond\r')
+ terminal.wait_for(b'Pure | second')
+ terminal.type('안녕'.encode() + b'\x1b[D' + '하'.encode() + b'\x13')
+ terminal.wait_for('안하녕'.encode())
+ wait_stored(editor, store, 'second', '안하녕'.encode(), 1)
+ terminal.resize(32, 100)
+ terminal.wait_for(b'Pure | second')
+ terminal.type(b'\x0fnote\r')
+ terminal.wait_for(b'Pure | note')
+ terminal.type(b'\x0c')
+ listing = terminal.wait_for(b'Pure | documents')
+ assert b'note' in listing and b'second' in listing, listing[-1000:]
+ terminal.type(b'\x1b[B\r')
+ terminal.wait_for(b'Pure | second')
+ terminal.type(b'\x0c\x1b[A\r')
+ terminal.wait_for(b'Pure | note')
+ terminal.type(b'\x0c')
+ terminal.wait_for(b'Pure | documents')
+ (store / 'obj-second').unlink()
+ terminal.type(b'\x1b[B\r')
+ terminal.wait_for(b'Document disappeared; refresh the list')
+ terminal.type(b'\x1b')
+ terminal.wait_for(b'Pure | note')
+ terminal.type(b'!')
+ terminal.type(b'\x0c')
+ terminal.wait_for(b'Save or reload the draft before browsing')
+ external = root / 'external'
+ external.write_bytes(b' remote')
+ command(*editor, '--store', store, 'edit', 'note', '1', '11', '0', external)
+ terminal.type(b'\x13')
+ terminal.wait_for(b'Version conflict')
+ assert shown(editor, store, 'note') == (b'hello Pu!re remote', '2')
+ small_peak = memory_kib(terminal.process.pid, 'VmHWM:', portable)
+ finally:
+ terminal.close(discard=True)
+
+ multiline = b'first\n\tsecond\nthird'
+ insert = root / 'multiline-insert'
+ insert.write_bytes(multiline)
+ command(*editor, '--store', store, 'edit', 'multiline', '0', '0', '0', insert)
+ terminal = Terminal(binary, program, store, 'multiline')
+ try:
+ terminal.resize(25, 80)
+ terminal.wait_for(b'third')
+ terminal.type(b'!\x13')
+ wait_stored(editor, store, 'multiline', multiline + b'!', 2)
+ finally:
+ terminal.close()
+ terminal = Terminal(binary, program, store, 'multiline')
+ terminal.resize(25, 80)
+ terminal.wait_for(b'third!')
+ terminal.close()
+
+ rows = [f'line-{index:02}'.encode() for index in range(60)]
+ insert.write_bytes(b'\n'.join(rows))
+ command(*editor, '--store', store, 'edit', 'rows', '0', '0', '0', insert)
+ terminal = Terminal(binary, program, store, 'rows')
+ try:
+ terminal.type(b'\x1b[A' * 3 + b'X\x13')
+ rows[56] += b'X'
+ wait_stored(editor, store, 'rows', b'\n'.join(rows), 2)
+ terminal.wait_for(b'line-56X')
+ finally:
+ terminal.close()
+
+ large = b'Q' * 1_048_576
+ insert = root / 'large-insert'
+ insert.write_bytes(large)
+ command(*editor, '--store', store, 'edit', 'large', '0', '0', '0', insert)
+ terminal = Terminal(binary, program, store, 'large')
+ try:
+ terminal.type(b'Z')
+ terminal.wait_for(b'Z')
+ terminal.type(b'\x13')
+ wait_stored(editor, store, 'large', large + b'Z', 2)
+ large_peak = memory_kib(terminal.process.pid, 'VmHWM:', portable)
+ finally:
+ terminal.close()
+ if rss_limit_kib:
+ assert large_peak <= rss_limit_kib, (large_peak, rss_limit_kib)
+
+ unicode_body = '안녕'.encode() * 174_762
+ insert.write_bytes(unicode_body)
+ command(*editor, '--store', store, 'edit', 'unicode', '0', '0', '0', insert)
+ terminal = Terminal(binary, program, store, 'unicode')
+ try:
+ terminal.type(b'K')
+ terminal.wait_for(b'K')
+ terminal.type(b'\x1b[HX')
+ terminal.wait_for(b'X' + '안녕'.encode())
+ terminal.type(b'\x13')
+ wait_stored(editor, store, 'unicode', b'X' + unicode_body + b'K', 2)
+ finally:
+ terminal.close()
+
+ listed = root / 'listed-store'
+ insert.write_bytes(b'X')
+ for index in range(1024):
+ command(*editor, '--store', listed, 'edit', f'doc{index:04}', '0', '0', '0', insert)
+ terminal = Terminal(binary, program, listed, 'doc0000')
+ try:
+ terminal.type(b'\x0c')
+ terminal.wait_for(b'Pure | documents | 1024 keys')
+ terminal.resize(8, 12)
+ terminal.wait_for(b'\033[8;1H')
+ terminal.resize(24, 80)
+ terminal.wait_for(b'Pure | documents | 1024 keys')
+ terminal.type(b'\x1b[F\r')
+ terminal.wait_for(b'Pure | doc1023')
+ assert shown(editor, listed, 'doc1023') == (b'X', '1')
+ terminal.type(b'\x0c')
+ terminal.wait_for(b'Pure | documents | 1024 keys')
+ terminal.type(b'doc0919')
+ terminal.wait_for(b'Find: doc0919_')
+ terminal.type(b'\r')
+ terminal.wait_for(b'Pure | doc0919')
+ assert shown(editor, listed, 'doc0919') == (b'X', '1')
+ terminal.type(b'\x0czz')
+ terminal.wait_for(b'No matching key')
+ terminal.type(b'\r')
+ terminal.wait_for(b'No matching key')
+ terminal.type(b'\x7f\x7fdoc1023\r')
+ terminal.wait_for(b'Pure | doc1023')
+ list_peak = memory_kib(terminal.process.pid, 'VmHWM:', portable)
+ finally:
+ terminal.close()
+ if rss_limit_kib:
+ assert list_peak <= rss_limit_kib, (list_peak, rss_limit_kib)
+
+ if source:
+ alternate = root / 'alternate.pure'
+ definition = program.read_text()
+ fields = ' start: u32le;\n remove: u32le;'
+ assert fields in definition
+ alternate.write_text(definition.replace(fields,
+ ' remove: u32le;\n start: u32le;'))
+ alternate_store = root / 'alternate-store'
+ terminal = Terminal(binary, alternate, alternate_store, 'different_layout')
+ try:
+ terminal.type(b'abcdef\x13')
+ wait_stored(editor, alternate_store, 'different_layout', b'abcdef', 1)
+ terminal.type(b'\x1b[D\x1b[D\x1b[D!\x13')
+ wait_stored(editor, alternate_store, 'different_layout', b'abc!def', 2)
+ finally:
+ terminal.close()
+
+ terminal = Terminal(binary, program, store, 'note')
+ terminal.signal_close()
+ return {'profile': 'native-source-document-terminal-editor' if source else
+ 'native-fixed-document-terminal-editor',
+ 'checks': (['source parse and incompatible definitions fail before store creation',
+ 'source CLI and TUI read the same document',
+ 'changed source field layout drives TUI input encoding'] if source else []) +
+ ['cursor insertion and save through terminal', 'open another key',
+ 'bounded document browser selects keys and protects unsaved draft',
+ 'UTF-8 codepoint movement, visible redraw and edit', 'resize redraw',
+ 'external revision conflict preserves draft',
+ 'stored multiline and tabbed document survives edit and reopen',
+ 'cached viewport preserves vertical movement across many rows',
+ 'one MiB document viewport, edit and fresh CLI restore',
+ 'one MiB UTF-8 viewport and edit before cached anchor',
+ '1,024 real documents listed, searched, resized and opened' +
+ (' within RSS gate' if not portable else ''),
+ 'terminal mode restored after key and signal exit'],
+ 'small_peak_rss_kib': small_peak,
+ 'one_mib_peak_rss_kib': large_peak,
+ 'one_thousand_key_list_peak_rss_kib': list_peak,
+ 'one_mib_peak_rss_limit_kib': rss_limit_kib,
+ 'portable': portable,
+ 'terminal_locale': utf8_locale(),
+ 'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest()}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--build', type=Path, default=HERE / 'build')
+ parser.add_argument('--rss-limit-kib', type=int, default=4096,
+ help='0 skips the release RSS gate for sanitizer builds')
+ parser.add_argument('--source', action='store_true', help='check the source-loaded TUI')
+ parser.add_argument('--portable', action='store_true',
+ help='run all PTY behavior without Linux /proc RSS measurement')
+ parser.add_argument('--program', type=Path, help='definition for --source (including relocated bundles)')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ result = check(args.build, 0 if args.portable else args.rss_limit_kib,
+ args.source, args.program, args.portable)
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/check_window.py b/prototypes/connections/check_window.py
new file mode 100644
index 0000000..57c96ef
--- /dev/null
+++ b/prototypes/connections/check_window.py
@@ -0,0 +1,553 @@
+#!/usr/bin/env python3
+"""Real GTK/X11 document flow. Run under xvfb-run after `make window editor`."""
+import argparse
+import http.client
+import json
+import os
+from pathlib import Path
+import re
+import select
+import struct
+import subprocess
+import tempfile
+import time
+
+HERE = Path(__file__).resolve().parent
+BUILD = HERE / "build"
+PROGRAM = HERE / "examples/editor.pure"
+
+
+def command(*args, input=None):
+ result = subprocess.run(args, input=input, capture_output=True, timeout=15)
+ if result.returncode:
+ raise AssertionError((args, result.returncode, result.stdout, result.stderr))
+ return result.stdout
+
+
+def xdo(*args):
+ return command("xdotool", *args).decode().strip()
+
+
+def switch_document(window, key):
+ xdo("key", "ctrl+o")
+ xdo("key", "ctrl+a")
+ xdo("type", "--clearmodifiers", key)
+ xdo("key", "Return")
+ for _ in range(50):
+ title = xdo("getwindowname", window)
+ if f"{key} · Pure document" in title:
+ return
+ time.sleep(0.05)
+ raise AssertionError((key, title))
+
+
+def store_cli(directory, *args):
+ return subprocess.run(
+ [str(BUILD / "pure-edit"), "--program", str(PROGRAM),
+ "--store", str(directory), *args], capture_output=True, timeout=15
+ )
+
+
+def read_document(directory, key, revision):
+ for _ in range(40):
+ result = store_cli(directory, "show", key)
+ if result.returncode == 0:
+ metadata = json.loads(result.stderr)
+ if metadata["revision"] == str(revision):
+ return result.stdout
+ time.sleep(0.1)
+ raise AssertionError((key, revision, result.returncode, result.stdout, result.stderr))
+
+
+def remote_edit(directory, key, revision, offset, inserted):
+ server = subprocess.Popen(
+ [str(BUILD / "pure-connections"), "--program", str(PROGRAM),
+ "--store", str(directory), "--port", "0"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ )
+ try:
+ ready, _, _ = select.select([server.stdout], [], [], 5)
+ assert ready, "document server did not start"
+ port = json.loads(server.stdout.readline())["port"]
+ connection = http.client.HTTPConnection("127.0.0.1", port, timeout=5)
+ try:
+ body = struct.pack("<II", offset, 0) + inserted
+ connection.request("PUT", f"/objects/{key}", body,
+ {"Content-Length": str(len(body)), "If-Match": f'"{revision}"'})
+ response = connection.getresponse()
+ received = response.read()
+ assert response.status == 200 and response.getheader("ETag") == f'"{revision + 1}"'
+ assert received == inserted
+ finally:
+ connection.close()
+ finally:
+ server.terminate()
+ try:
+ server.communicate(timeout=5)
+ except subprocess.TimeoutExpired:
+ server.kill()
+ server.communicate(timeout=5)
+
+
+def cli_external_edit(directory, key, revision, offset, inserted):
+ payload = directory / 'external-insert'
+ payload.write_bytes(inserted)
+ result = store_cli(directory, 'edit', key, str(revision), str(offset), '0', str(payload))
+ assert result.returncode == 0, result.stderr
+
+
+def start_window(directory, key):
+ environment = dict(os.environ, GSK_RENDERER="cairo", GDK_DISABLE="gl,vulkan",
+ GTK_A11Y="none")
+ app = subprocess.Popen(
+ [str(BUILD / "pure-edit-window"), "--program", str(PROGRAM),
+ "--store", str(directory), key], env=environment,
+ stdout=subprocess.DEVNULL, stderr=subprocess.PIPE
+ )
+ for _ in range(60):
+ found = subprocess.run(["xdotool", "search", "--name", "Pure document"],
+ capture_output=True, timeout=5)
+ if found.returncode == 0:
+ window = found.stdout.decode().splitlines()[0]
+ focused = subprocess.run(["xdotool", "windowfocus", "--sync", window],
+ capture_output=True, timeout=5)
+ if focused.returncode:
+ time.sleep(0.1)
+ continue
+ xdo("mousemove", "--window", window, "120", "150")
+ xdo("click", "1")
+ return app, window
+ if app.poll() is not None:
+ break
+ time.sleep(0.1)
+ app.terminate()
+ _, error = app.communicate(timeout=5)
+ raise AssertionError(("window failed to open", error))
+
+
+def stop_window(app):
+ app.terminate()
+ try:
+ _, error = app.communicate(timeout=5)
+ except subprocess.TimeoutExpired:
+ app.kill()
+ _, error = app.communicate(timeout=5)
+ assert app.returncode in (0, -15), error
+ assert b"Gtk-CRITICAL" not in error and b"runtime error:" not in error, error
+ return error
+
+
+def clipboard():
+ xdo("key", "ctrl+a")
+ xdo("key", "ctrl+c")
+ time.sleep(0.1)
+ return command("xclip", "-selection", "clipboard", "-o", "-t", "UTF8_STRING")
+
+
+def rss_kib(pid):
+ for line in Path(f"/proc/{pid}/status").read_text().splitlines():
+ if line.startswith("VmRSS:"):
+ return int(line.split()[1])
+ raise AssertionError("VmRSS unavailable")
+
+
+def rss_breakdown_kib(pid):
+ groups = {'heap': 0, 'anonymous': 0, 'file': 0, 'stack': 0, 'other': 0}
+ category = 'other'
+ for line in Path(f"/proc/{pid}/smaps").read_text().splitlines():
+ if re.match(r'^[0-9a-f]+-[0-9a-f]+ ', line):
+ fields = line.split(maxsplit=5)
+ name = fields[5] if len(fields) > 5 else ''
+ category = ('heap' if name == '[heap]' else
+ 'stack' if name.startswith('[stack') else
+ 'anonymous' if not name or name.startswith('[anon:') else
+ 'file' if name.startswith('/') else 'other')
+ elif line.startswith('Rss:'):
+ groups[category] += int(line.split()[1])
+ return groups
+
+
+def check(check_key_switch=True, switch_rounds=16, diagnose_maps=False,
+ switch_mode='alternate', graceful_large_close=False, settle_seconds=0,
+ large_line_width=80):
+ global PROGRAM
+ assert os.environ.get("DISPLAY"), "run under xvfb-run or another X11 display"
+ with tempfile.TemporaryDirectory(prefix="pure-document-window-") as name:
+ directory = Path(name)
+ source_definition = PROGRAM.read_bytes()
+ PROGRAM = directory / "editable.pure"
+ PROGRAM.write_bytes(source_definition)
+ app, _ = start_window(directory, "note")
+ try:
+ xdo("type", "--clearmodifiers", "--delay", "15", "hello Pure")
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "note", 1) == b"hello Pure"
+ xdo("type", "--clearmodifiers", "!")
+ if (BUILD / 'pure-connections').exists():
+ remote_edit(directory, "note", 1, 10, b" remote")
+ external_host = 'http'
+ else:
+ cli_external_edit(directory, "note", 1, 10, b" remote")
+ external_host = 'cli'
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "note", 2) == b"hello Pure remote"
+ assert clipboard() == b"hello Pure!", "conflict replaced the local draft"
+ xdo("key", "ctrl+w")
+ time.sleep(0.15)
+ assert app.poll() is None, "unsaved draft closed without confirmation"
+ xdo("key", "Escape")
+ time.sleep(0.1)
+ assert app.poll() is None and clipboard() == b"hello Pure!"
+ finally:
+ stop_window(app)
+
+ if check_key_switch:
+ # One native window must switch among stored objects without dropping
+ # a draft or installing a non-text object as the active document.
+ app, window = start_window(directory, "first")
+ try:
+ xdo("type", "--clearmodifiers", "alpha")
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "first", 1) == b"alpha"
+ xdo("key", "ctrl+o")
+ xdo("key", "ctrl+a")
+ xdo("type", "--clearmodifiers", "second")
+ xdo("key", "Return")
+ assert "second · Pure document" in xdo("getwindowname", window)
+ xdo("type", "--clearmodifiers", "beta")
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "second", 1) == b"beta"
+ xdo("type", "--clearmodifiers", "!")
+ xdo("key", "ctrl+o")
+ xdo("key", "ctrl+a")
+ xdo("type", "--clearmodifiers", "third")
+ xdo("key", "Return")
+ assert "second · Pure document" in xdo("getwindowname", window)
+ xdo("mousemove", "--window", window, "120", "150")
+ xdo("click", "1")
+ assert clipboard() == b"beta!", "switch discarded the document draft"
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "second", 2) == b"beta!"
+ xdo("key", "ctrl+o")
+ xdo("key", "ctrl+a")
+ xdo("type", "--clearmodifiers", "third")
+ xdo("key", "Return")
+ assert "third · Pure document" in xdo("getwindowname", window)
+ xdo("type", "--clearmodifiers", "gamma")
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "third", 1) == b"gamma"
+
+ xdo("key", "ctrl+o")
+ xdo("key", "ctrl+a")
+ xdo("type", "--clearmodifiers", "bad/key")
+ xdo("key", "Return")
+ assert "third · Pure document" in xdo("getwindowname", window)
+ payload = directory / "binary-payload"
+ payload.write_bytes(b"\x00")
+ assert store_cli(directory, "edit", "binary", "0", "0", "0", str(payload)).returncode == 0
+ xdo("key", "ctrl+o")
+ xdo("key", "ctrl+a")
+ xdo("type", "--clearmodifiers", "binary")
+ xdo("key", "Return")
+ assert "third · Pure document" in xdo("getwindowname", window)
+ assert read_document(directory, "third", 1) == b"gamma"
+
+ xdo("key", "ctrl+shift+d")
+ xdo("key", "ctrl+End")
+ xdo("type", "--clearmodifiers", " draft")
+ xdo("key", "ctrl+o")
+ xdo("key", "ctrl+a")
+ xdo("type", "--clearmodifiers", "fourth")
+ xdo("key", "Return")
+ assert "third · Pure document" in xdo("getwindowname", window)
+ xdo("key", "ctrl+shift+d")
+ xdo("key", "ctrl+shift+d")
+ assert b" draft" in clipboard(), "switch discarded the definition draft"
+ finally:
+ stop_window(app)
+
+ app, _ = start_window(directory, "empty")
+ try:
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "empty", 1) == b""
+ finally:
+ stop_window(app)
+ app, _ = start_window(directory, "empty")
+ try:
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "empty", 1) == b""
+ finally:
+ stop_window(app)
+
+ insertion = directory / "remote-insert"
+ insertion.write_bytes("가나다".encode())
+ initial = store_cli(directory, "edit", "unicode", "0", "0", "0", str(insertion))
+ assert initial.returncode == 0, initial.stderr
+ app, _ = start_window(directory, "unicode")
+ try:
+ assert clipboard() == "가나다".encode()
+ # xclip forks an owner process which keeps inherited pipe handles.
+ pasted = subprocess.run(["xclip", "-selection", "clipboard", "-i",
+ "-t", "UTF8_STRING"], input="각나다".encode(),
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
+ timeout=5)
+ assert pasted.returncode == 0
+ xdo("key", "ctrl+v")
+ time.sleep(0.15)
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "unicode", 2) == "각나다".encode()
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "unicode", 2) == "각나다".encode(), "no-op save changed revision"
+ finally:
+ stop_window(app)
+ app, _ = start_window(directory, "unicode")
+ try:
+ assert clipboard() == "각나다".encode(), "new process did not restore the edit"
+ finally:
+ stop_window(app)
+
+ # A real 1 MiB document crosses the GTK boundary, but an edit still
+ # carries only the prepared two u32 fields and one changed byte.
+ large = ((b"A" * (large_line_width - 1) + b"\n") *
+ (1_048_576 // large_line_width) +
+ b"A" * (1_048_576 % large_line_width))
+ assert len(large) == 1_048_576
+ insertion.write_bytes(large)
+ initial = store_cli(directory, "edit", "large", "0", "0", "0", str(insertion))
+ assert initial.returncode == 0, initial.stderr
+ if check_key_switch:
+ other_large = b"B" + large[1:]
+ other_revision = 1
+ insertion.write_bytes(other_large)
+ assert store_cli(directory, "edit", "large_other", "0", "0", "0",
+ str(insertion)).returncode == 0
+ switch_rss_samples = []
+ switch_map_samples = []
+ app, large_window = start_window(directory, "large")
+ try:
+ time.sleep(0.25)
+ resident = rss_kib(app.pid)
+ xdo("key", "ctrl+End")
+ xdo("key", "BackSpace")
+ xdo("type", "--clearmodifiers", "Z")
+ xdo("key", "ctrl+s")
+ stored = read_document(directory, "large", 2)
+ assert stored == large[:-1] + b"Z"
+ if check_key_switch:
+ if switch_mode == 'same-body':
+ insertion.write_bytes(stored)
+ assert store_cli(directory, "edit", "large_other", "1", "0",
+ str(len(other_large)), str(insertion)).returncode == 0
+ other_large = stored
+ other_revision = 2
+ for step in range(switch_rounds):
+ key = "large" if switch_mode == 'same' else (
+ "large_other" if step % 2 == 0 else "large")
+ switch_document(large_window, key)
+ if (step + 1) % 8 == 0:
+ switch_rss_samples.append(rss_kib(app.pid))
+ if diagnose_maps:
+ switch_map_samples.append(rss_breakdown_kib(app.pid))
+ assert read_document(directory, "large", 2) == stored
+ assert read_document(directory, "large_other", other_revision) == other_large
+ if settle_seconds:
+ time.sleep(settle_seconds)
+ settled_rss = rss_kib(app.pid)
+ settled_maps = rss_breakdown_kib(app.pid) if diagnose_maps else None
+ if graceful_large_close:
+ xdo("key", "ctrl+w")
+ _, error = app.communicate(timeout=15)
+ assert app.returncode == 0, (app.returncode, error[-4000:])
+ finally:
+ large_stderr = stop_window(app)
+
+ # Author the same running document app in the native window. Failed
+ # preparation and an external source conflict must preserve the draft.
+ changed_definition = source_definition.replace(b"reply(saved, edit.insert);",
+ b"reply(saved);")
+ assert changed_definition != source_definition
+ app, window = start_window(directory, "authored")
+ try:
+ xdo("key", "ctrl+shift+d")
+ time.sleep(0.25)
+ pasted = subprocess.run(["xclip", "-selection", "clipboard", "-i",
+ "-t", "UTF8_STRING"], input=changed_definition,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
+ timeout=5)
+ assert pasted.returncode == 0
+ xdo("key", "ctrl+a")
+ xdo("key", "ctrl+v")
+ xdo("key", "ctrl+shift+s")
+ for _ in range(30):
+ if PROGRAM.read_bytes() == changed_definition:
+ break
+ time.sleep(0.1)
+ assert PROGRAM.read_bytes() == changed_definition, "definition was not saved"
+ assert "definition 2" in xdo("getwindowname", window)
+ xdo("key", "ctrl+shift+d")
+ xdo("type", "--clearmodifiers", "Z")
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "authored", 1) == b"Z"
+ assert "output 0 B" in xdo("getwindowname", window), "old reply plan stayed active"
+
+ xdo("key", "ctrl+shift+d")
+ cannot_save = changed_definition + b"\n// source write must fail\n"
+ pasted = subprocess.run(["xclip", "-selection", "clipboard", "-i",
+ "-t", "UTF8_STRING"], input=cannot_save,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
+ timeout=5)
+ assert pasted.returncode == 0
+ xdo("key", "ctrl+a")
+ xdo("key", "ctrl+v")
+ prior_mode = directory.stat().st_mode & 0o777
+ os.chmod(directory, 0o500)
+ try:
+ xdo("key", "ctrl+shift+s")
+ finally:
+ os.chmod(directory, prior_mode)
+ assert PROGRAM.read_bytes() == changed_definition, "failed source save changed the file"
+ assert "definition 2" in xdo("getwindowname", window)
+ assert clipboard() == cannot_save, "failed source save dropped the draft"
+
+ partial_read = source_definition.replace(
+ b"reply(document, document.body);",
+ b"reply(document, range(document.body, 0, 1));")
+ assert partial_read != source_definition
+ pasted = subprocess.run(["xclip", "-selection", "clipboard", "-i",
+ "-t", "UTF8_STRING"], input=partial_read,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
+ timeout=5)
+ assert pasted.returncode == 0
+ xdo("key", "ctrl+a")
+ xdo("key", "ctrl+v")
+ xdo("key", "ctrl+shift+s")
+ assert PROGRAM.read_bytes() == changed_definition, "partial read made document editing unsafe"
+ assert "definition 2" in xdo("getwindowname", window)
+
+ invalid = b"not a Pure definition\n"
+ pasted = subprocess.run(["xclip", "-selection", "clipboard", "-i",
+ "-t", "UTF8_STRING"], input=invalid,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
+ timeout=5)
+ assert pasted.returncode == 0
+ xdo("key", "ctrl+a")
+ xdo("key", "ctrl+v")
+ xdo("key", "ctrl+shift+s")
+ assert PROGRAM.read_bytes() == changed_definition
+ assert "definition 2" in xdo("getwindowname", window)
+ xdo("key", "ctrl+a")
+ xdo("key", "ctrl+c")
+ assert clipboard() == invalid, "invalid definition draft was discarded"
+
+ local_draft = changed_definition + b"\n// local draft\n"
+ external = source_definition + b"\n// external change\n"
+ pasted = subprocess.run(["xclip", "-selection", "clipboard", "-i",
+ "-t", "UTF8_STRING"], input=local_draft,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
+ timeout=5)
+ assert pasted.returncode == 0
+ xdo("key", "ctrl+a")
+ xdo("key", "ctrl+v")
+ PROGRAM.write_bytes(external)
+ xdo("key", "ctrl+shift+s")
+ assert PROGRAM.read_bytes() == external, "external definition was overwritten"
+ assert "definition 2" in xdo("getwindowname", window)
+ xdo("key", "ctrl+w")
+ time.sleep(0.15)
+ assert app.poll() is None, "unsaved definition draft closed without confirmation"
+ xdo("key", "Escape")
+ time.sleep(0.1)
+ assert app.poll() is None
+ xdo("mousemove", "--window", window, "680", "326")
+ xdo("click", "1") # Explicitly discard the source draft and reload disk.
+ xdo("key", "ctrl+shift+s")
+ assert PROGRAM.read_bytes() == external
+ assert "definition 3" in xdo("getwindowname", window)
+ xdo("key", "ctrl+shift+d")
+ xdo("type", "--clearmodifiers", "Y")
+ xdo("key", "ctrl+s")
+ assert len(read_document(directory, "authored", 2)) == 2
+ assert "output 1 B" in xdo("getwindowname", window), "reloaded definition did not run"
+ finally:
+ stop_window(app)
+
+ app, window = start_window(directory, "author-restored")
+ try:
+ xdo("type", "--clearmodifiers", "R")
+ xdo("key", "ctrl+s")
+ assert read_document(directory, "author-restored", 1) == b"R"
+ assert "output 1 B" in xdo("getwindowname", window), "saved definition did not restore"
+ finally:
+ stop_window(app)
+
+ result = {"gtk_cli_write": "pass", f"{external_host}_conflict_preserves_draft": "pass",
+ "unsaved_close_guard": "pass",
+ "empty_document_restore": "pass",
+ "utf8_boundary_and_restart": "pass", "unchanged_save_keeps_revision": "pass",
+ "one_mib_document_one_byte_edit": "pass", "large_window_rss_kib": resident,
+ "native_definition_apply_and_running_output": "pass",
+ "definition_restores_in_new_window": "pass",
+ "partial_read_definition_rejected": "pass",
+ "source_write_failure_preserves_active_definition": "pass",
+ "invalid_and_external_definition_preserve_draft": "pass",
+ "reloaded_definition_installs_without_rewriting_source": "pass",
+ "profile": "optional-native-document-window"}
+ if check_key_switch:
+ result["multi_document_switch_preserves_draft"] = "pass"
+ result["large_switch_rss_samples_kib"] = switch_rss_samples
+ result["large_switch_mode"] = switch_mode
+ result["large_line_width"] = large_line_width
+ if settle_seconds:
+ result["large_switch_settled_rss_kib"] = settled_rss
+ if diagnose_maps:
+ result["large_switch_settled_map_kib"] = settled_maps
+ if diagnose_maps:
+ result["large_switch_map_samples_kib"] = switch_map_samples
+ allocations = re.findall(
+ rb'PURE_MALLOC key=([^ ]+) arena=(\d+) used=(\d+) free=(\d+) mapped=(\d+)',
+ large_stderr)
+ if allocations:
+ result['large_malloc_samples_bytes'] = [
+ {'key': key.decode(), 'arena': int(arena), 'used': int(used),
+ 'free': int(free), 'mapped': int(mapped)}
+ for key, arena, used, free, mapped in allocations]
+ return result
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("--output", type=Path)
+ parser.add_argument("--build", type=Path, default=BUILD)
+ parser.add_argument("--program", type=Path, default=PROGRAM)
+ parser.add_argument("--legacy-window", action="store_true",
+ help="check an archived window built before document switching existed")
+ parser.add_argument("--switch-rounds", type=int, default=16,
+ help="number of alternating 1 MiB document opens, in groups of eight")
+ parser.add_argument("--diagnose-maps", action="store_true",
+ help="record RSS by Linux mapping category after each eight switches")
+ parser.add_argument("--switch-mode", choices=('alternate', 'same', 'same-body'),
+ default='alternate',
+ help="alternate two different or identical documents, or reopen one")
+ parser.add_argument("--graceful-large-close", action="store_true",
+ help="exit the large-text window normally so leak detectors can run")
+ parser.add_argument("--settle-seconds", type=float, default=0,
+ help="wait after the final switch, then sample RSS again")
+ parser.add_argument("--large-line-width", type=int, default=80,
+ help="bytes per line in the 1 MiB fixture (default: 80)")
+ args = parser.parse_args()
+ if args.switch_rounds < 8 or args.switch_rounds > 128 or args.switch_rounds % 8:
+ parser.error('--switch-rounds must be a multiple of eight between 8 and 128')
+ if args.settle_seconds < 0 or args.settle_seconds > 30:
+ parser.error('--settle-seconds must be between zero and 30')
+ if args.large_line_width < 2 or args.large_line_width > 1_048_576:
+ parser.error('--large-line-width must be between 2 and 1048576')
+ BUILD = args.build.resolve()
+ PROGRAM = args.program.resolve()
+ result = check(not args.legacy_window, args.switch_rounds,
+ args.diagnose_maps, args.switch_mode, args.graceful_large_close,
+ args.settle_seconds, args.large_line_width)
+ text = json.dumps(result, sort_keys=True) + "\n"
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(text)
+ print(text, end="")
diff --git a/prototypes/connections/check_write_cost.py b/prototypes/connections/check_write_cost.py
new file mode 100644
index 0000000..4dcfe03
--- /dev/null
+++ b/prototypes/connections/check_write_cost.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python3
+"""Trace one real document replacement through each selected storage binary."""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import re
+import subprocess
+import tempfile
+
+HERE = Path(__file__).resolve().parent
+WRITE = re.compile(r'\bwrite\(\d+<([^>]+)>, .*?, (\d+)\) = (\d+)$')
+
+
+def command(*args):
+ result = subprocess.run([str(arg) for arg in args], capture_output=True, timeout=20)
+ if result.returncode:
+ raise AssertionError((result.args, result.returncode, result.stderr[-1000:]))
+ return result
+
+
+def inspect(binary, root, key, initial, patch, offset):
+ program = HERE / 'examples/editor.pure'
+ store = root / (binary.parent.name + '-' + key)
+ base = [binary, '--program', program, '--store', store]
+ command(*base, 'edit', key, 0, 0, 0, initial)
+ trace = root / (binary.parent.name + '-' + key + '.trace')
+ command('strace', '-qq', '-e', 'trace=write,pwrite64,writev,pwritev,fsync',
+ '-yy', '-o', trace, *base, 'edit', key, 1, offset, 1, patch)
+ expected = initial.read_bytes()[:offset] + patch.read_bytes() + initial.read_bytes()[offset + 1:]
+ assert command(*base, 'show', key).stdout == expected
+ writes = []
+ for line in trace.read_text().splitlines():
+ if '/.pending-' not in line and '/dat-' + key + '-' not in line:
+ continue
+ if not any(word in line for word in ('write(', 'pwrite64(', 'writev(', 'pwritev(')):
+ continue
+ match = WRITE.search(line)
+ if not match:
+ raise AssertionError(f'unaccounted object write: {line}')
+ requested, completed = int(match[2]), int(match[3])
+ if requested != completed:
+ raise AssertionError(f'partial object write: {line}')
+ writes.append(completed)
+ return {'object_write_syscall_bytes': sum(writes), 'object_write_calls': len(writes),
+ 'object_files': {item.name: item.stat().st_size for item in store.iterdir()
+ if item.name.startswith(('obj-', 'dat-'))},
+ 'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest()}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--flat', type=Path, required=True)
+ parser.add_argument('--paged', '--candidate', dest='candidate', type=Path, required=True)
+ parser.add_argument('--candidate-mode', choices=('paged', 'hybrid'), default='paged')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ with tempfile.TemporaryDirectory(prefix='pure-write-cost-') as name:
+ root = Path(name)
+ initial, tiny, patch = root / 'initial', root / 'tiny', root / 'patch'
+ initial.write_bytes(b'A' * 1_048_576)
+ tiny.write_bytes(b'A')
+ patch.write_bytes(b'Z')
+ large_flat = inspect(args.flat.resolve(), root, 'large', initial, patch, 1_048_575)
+ large_paged = inspect(args.candidate.resolve(), root, 'large', initial, patch, 1_048_575)
+ tiny_flat = inspect(args.flat.resolve(), root, 'tiny', tiny, patch, 0)
+ tiny_paged = inspect(args.candidate.resolve(), root, 'tiny', tiny, patch, 0)
+ if [large_flat['object_write_syscall_bytes'], large_paged['object_write_syscall_bytes'],
+ tiny_flat['object_write_syscall_bytes'], tiny_paged['object_write_syscall_bytes']] != \
+ [1_048_600, 16_944, 25, 25 if args.candidate_mode == 'hybrid' else 16_440]:
+ raise AssertionError((large_flat, large_paged, tiny_flat, tiny_paged))
+ result = {'profile': 'linux-aarch64-16k-page-document-replacement',
+ 'candidate_mode': args.candidate_mode,
+ 'workloads': ['replace last byte of 1 MiB document', 'replace one-byte document'],
+ 'unit': 'successful user-space write syscall bytes targeting object files',
+ 'excludes': 'physical device writes, filesystem journal, metadata and directory sync cost',
+ 'one_mib': {'flat': large_flat, args.candidate_mode: large_paged,
+ f'flat_to_{args.candidate_mode}_ratio': large_flat['object_write_syscall_bytes'] /
+ large_paged['object_write_syscall_bytes']},
+ 'one_byte': {'flat': tiny_flat, args.candidate_mode: tiny_paged,
+ f'{args.candidate_mode}_to_flat_ratio': tiny_paged['object_write_syscall_bytes'] /
+ tiny_flat['object_write_syscall_bytes']}}
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/compile-program.c b/prototypes/connections/compile-program.c
new file mode 100644
index 0000000..7e291f3
--- /dev/null
+++ b/prototypes/connections/compile-program.c
@@ -0,0 +1,116 @@
+#include "program.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+/* Build-time preparation. The generated initializer is compiled with the
+ * target, so the run-only host contains neither this tool nor the parser. */
+static void region(FILE *out, PureRegion value) {
+ fprintf(out, "{.offset=%zu,.length=%zu,.to_end=%s}", value.offset,
+ value.length, value.to_end ? "true" : "false");
+}
+
+static void index_value(FILE *out, PureIndex value) {
+ fprintf(out, "{.value=%zu,.from_u32le=%s}", value.value,
+ value.from_u32le ? "true" : "false");
+}
+
+static void emit(FILE *out, const PureProgram *p) {
+ fputs("/* Generated from a validated .pure definition. Do not edit. */\n"
+ "static const PureProgram pure_embedded_program = {\n.read=", out);
+ region(out, p->read);
+ fputs(",\n.write=", out);
+ region(out, p->write);
+ fputs(",\n.reply=", out);
+ region(out, p->reply);
+ fprintf(out, ",\n.read_required=%zu,.input_required=%zu,\n"
+ ".view_definitions=%zu,.range_definitions=%zu,\n"
+ ".write_step=%zu,.reply_step=%zu,.input_steps=%zu,\n",
+ p->read_required, p->input_required, p->view_definitions,
+ p->range_definitions, p->write_step, p->reply_step, p->input_steps);
+ if (p->input_steps) fputs(".steps={\n", out);
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ fputs("{.source=", out);
+ region(out, step->source);
+ fprintf(out, ",.source_step=%zu,.offset=", step->source_step);
+ index_value(out, step->offset);
+ fputs(",.length=", out);
+ index_value(out, step->length);
+ fputs("},\n", out);
+ }
+ if (p->input_steps) fputs("},\n", out);
+ fprintf(out, ".reply_input=%s,.splice=%s,\n.splice_offset=",
+ p->reply_input ? "true" : "false", p->splice ? "true" : "false");
+ index_value(out, p->splice_offset);
+ fputs(",.splice_remove=", out);
+ index_value(out, p->splice_remove);
+ fprintf(out, ",.splice_limit=%u\n};\n", p->splice_limit);
+}
+
+static bool same_file(const char *left_path, const char *right_path) {
+ FILE *left = fopen(left_path, "rb");
+ FILE *right = fopen(right_path, "rb");
+ if (!left || !right) {
+ if (left) fclose(left);
+ if (right) fclose(right);
+ return false;
+ }
+ bool same = true;
+ for (;;) {
+ int a = fgetc(left), b = fgetc(right);
+ if (a != b) { same = false; break; }
+ if (a == EOF) break;
+ }
+ same = same && !ferror(left) && !ferror(right);
+ int left_status = fclose(left), right_status = fclose(right);
+ if (left_status || right_status) same = false;
+ return same;
+}
+
+int main(int argc, char **argv) {
+ if (argc != 3) {
+ fputs("usage: pure-compile SOURCE.pure OUTPUT.h\n", stderr);
+ return 2;
+ }
+ struct stat source_info, output_info;
+ if (!stat(argv[1], &source_info) && !stat(argv[2], &output_info) &&
+ source_info.st_dev == output_info.st_dev &&
+ source_info.st_ino == output_info.st_ino) {
+ fputs("source and output must be different files\n", stderr);
+ return 2;
+ }
+ PureProgram program;
+ char error[160];
+ if (!pure_program_load(argv[1], &program, error, sizeof(error))) {
+ fprintf(stderr, "Program: %s\n", error);
+ return 2;
+ }
+ size_t path_size = strlen(argv[2]) + 5;
+ char *temporary = malloc(path_size);
+ if (!temporary) { fputs("output path allocation failed\n", stderr); return 2; }
+ snprintf(temporary, path_size, "%s.tmp", argv[2]);
+ FILE *out = fopen(temporary, "wb");
+ if (!out) { perror("output"); free(temporary); return 2; }
+ emit(out, &program);
+ if (fclose(out)) {
+ perror("output");
+ remove(temporary);
+ free(temporary);
+ return 2;
+ }
+ if (same_file(temporary, argv[2])) {
+ remove(temporary);
+ free(temporary);
+ return 0;
+ }
+ if (rename(temporary, argv[2])) {
+ perror("output");
+ remove(temporary);
+ free(temporary);
+ return 2;
+ }
+ free(temporary);
+ return 0;
+}
diff --git a/prototypes/connections/core-budget.json b/prototypes/connections/core-budget.json
new file mode 100644
index 0000000..ebe4675
--- /dev/null
+++ b/prototypes/connections/core-budget.json
@@ -0,0 +1,15 @@
+{
+ "profile": "opaque-definition-execution-core",
+ "max_text_bytes": 4864,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 120,
+ "work_slot_bytes": 216,
+ "ticket_bytes": 24,
+ "pointer_bytes": 8
+ },
+ "archive_members": ["runtime.o"],
+ "external_symbols_allowed": ["memcpy", "memmove", "memset", "strlen"],
+ "scope": "Opaque-definition execution, resource credits, completion and loans only. Document view/splice evaluation is linked into the selected adapter. Without opt-in PURE_RUNTIME_METRICS, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. This ceiling is a regression guard for this profile, not a universal runtime size promise."
+}
diff --git a/prototypes/connections/core-layout.c b/prototypes/connections/core-layout.c
new file mode 100644
index 0000000..f037c76
--- /dev/null
+++ b/prototypes/connections/core-layout.c
@@ -0,0 +1,14 @@
+#include "runtime.h"
+#include <stdio.h>
+
+/* Host-side measurement tool; never linked into libpure-execution.a. */
+int main(void) {
+ printf("{\"domain_bytes\":%zu,\"work_slot_bytes\":%zu,\"ticket_bytes\":%zu,"
+ "\"pointer_bytes\":%zu",
+ sizeof(PureRuntime), sizeof(PureWork), sizeof(PureTicket), sizeof(void *));
+#ifdef PURE_ASYNC_EFFECTS
+ printf(",\"effect_bytes\":%zu", sizeof(PureEffect));
+#endif
+ puts("}");
+ return 0;
+}
diff --git a/prototypes/connections/document-peer.c b/prototypes/connections/document-peer.c
new file mode 100644
index 0000000..9cbc64f
--- /dev/null
+++ b/prototypes/connections/document-peer.c
@@ -0,0 +1,330 @@
+#define _POSIX_C_SOURCE 200809L
+/* Selected document peer: same prepared program, store and execution core as
+ * pure-edit. TLS and the wire protocol remain outside libpure-execution.a. */
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include "../common/tls-link.h"
+#include <openssl/err.h>
+#include <openssl/sha.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+enum { REQUEST_BYTES = 14, REPLY_BYTES = 13, HELLO_BYTES = 40,
+ OP_READ = 1, OP_WRITE = 2, WANT_BODY = 0x80 };
+static const unsigned char alpn[] = {10, 'p','u','r','e','-','d','o','c','/','1'};
+static volatile sig_atomic_t stopping;
+static void signal_stop(int signum) { (void)signum; stopping = 1; }
+
+static uint32_t get32(const unsigned char *p) {
+ return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3];
+}
+static uint64_t get64(const unsigned char *p) {
+ uint64_t value = 0;
+ for (unsigned i = 0; i < 8; ++i) value = (value << 8) | p[i];
+ return value;
+}
+static void put32(unsigned char *p, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) p[i] = (unsigned char)(value >> (24 - 8 * i));
+}
+static void put64(unsigned char *p, uint64_t value) {
+ for (unsigned i = 0; i < 8; ++i) p[i] = (unsigned char)(value >> (56 - 8 * i));
+}
+#ifndef PURE_PEER_SERVER_ONLY
+static void put32le(unsigned char *p, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) p[i] = (unsigned char)(value >> (8 * i));
+}
+#endif
+static bool number(const char *text, uint64_t limit, uint64_t *out) {
+ if (!text || !*text) return false;
+ uint64_t value = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > limit || value > (limit - digit) / 10) return false;
+ value = value * 10 + digit;
+ }
+ *out = value;
+ return true;
+}
+static bool load_program(const char *path, PureProgram *program, unsigned char digest[32]) {
+ FILE *file = fopen(path, "rb");
+ if (!file) return false;
+ char source[PURE_PROGRAM_LIMIT + 1];
+ size_t length = fread(source, 1, sizeof(source), file);
+ bool bad = ferror(file) != 0;
+ if (fclose(file)) bad = true;
+ char error[160];
+ if (bad || !pure_program_parse(source, length, program, error, sizeof(error))) {
+ if (!bad) fprintf(stderr, "Program: %s\n", error);
+ return false;
+ }
+ return SHA256((const unsigned char *)source, length, digest) != NULL;
+}
+#ifndef PURE_PEER_SERVER_ONLY
+static bool edit_layout(const PureProgram *p, size_t *prefix) {
+ if (!p->splice || !p->write.to_end || p->write_step || p->input_steps ||
+ !p->splice_offset.from_u32le || !p->splice_remove.from_u32le) return false;
+ size_t start = p->splice_offset.value, remove = p->splice_remove.value;
+ *prefix = p->write.offset;
+ /* The convenience command is deliberately the eight-byte editor profile.
+ * Other authored layouts use apply, with no layout-specific wire fields. */
+ return *prefix == 8 && p->input_required <= 8 &&
+ ((start == 0 && remove == 4) || (start == 4 && remove == 0));
+}
+#endif
+static bool write_hello(PureLink *link, const unsigned char digest[32], uint64_t deadline) {
+ unsigned char hello[HELLO_BYTES] = {'P','D','O','C',1,0,0,0};
+ memcpy(hello + 8, digest, 32);
+ return pure_link_write(link, hello, sizeof(hello), deadline);
+}
+#ifndef PURE_PEER_SERVER_ONLY
+static bool read_hello(PureLink *link, const unsigned char digest[32], uint64_t deadline) {
+ unsigned char hello[HELLO_BYTES];
+ const unsigned char header[] = {'P','D','O','C',1,0,0,0};
+ return pure_link_read(link, hello, sizeof(hello), deadline) == 1 &&
+ !memcmp(hello, header, sizeof(header)) && !memcmp(hello + 8, digest, 32);
+}
+#endif
+/* The header always reports the logical output length. The requester chooses
+ * whether that borrowed output must cross this boundary at all. */
+static bool send_result(PureLink *link, PureOutcome outcome, bool want_body, uint64_t deadline) {
+ if (outcome.status > PURE_ALLOCATION || outcome.revision < 0 || outcome.body.size > PURE_OBJECT_LIMIT ||
+ (outcome.body.size && !outcome.body.data)) return false;
+ unsigned char header[REPLY_BYTES];
+ header[0] = (unsigned char)outcome.status;
+ put64(header + 1, (uint64_t)outcome.revision);
+ put32(header + 9, (uint32_t)outcome.body.size);
+ return pure_link_write(link, header, sizeof(header), deadline) &&
+ (!want_body || pure_link_write(link, outcome.body.data, outcome.body.size, deadline));
+}
+static bool serve_request(PureLink *link, PureRuntime *runtime, int *end) {
+ uint64_t deadline = pure_link_now_ms() + PURE_LINK_DEADLINE_MS;
+ unsigned char header[REQUEST_BYTES];
+ int got = pure_link_read(link, header, sizeof(header), deadline);
+ if (!got) { *end = 1; return true; }
+ if (got != 1) return false;
+ unsigned op = header[0] & ~WANT_BODY, key_size = header[1];
+ bool want_body = (header[0] & WANT_BODY) != 0;
+ uint64_t expected = get64(header + 2);
+ uint32_t body_size = get32(header + 10);
+ if ((op != OP_READ && op != OP_WRITE) || !key_size || key_size > 64 ||
+ expected > INT64_MAX || body_size > PURE_OBJECT_LIMIT ||
+ (op == OP_READ && (expected || body_size))) return false;
+ char key[65];
+ if (pure_link_read(link, key, key_size, deadline) != 1) return false;
+ if (memchr(key, 0, key_size)) return false;
+ key[key_size] = 0;
+ PureTicket ticket;
+ PureResult accepted = pure_runtime_accept(runtime, op == OP_READ ? PURE_INPUT_READ : PURE_INPUT_WRITE,
+ key, (int64_t)expected, body_size, &ticket);
+ if (accepted != PURE_OK) {
+ /* The body is intentionally not consumed after failed admission. */
+ PureOutcome error = {.status = accepted};
+ (void)send_result(link, error, want_body, deadline);
+ return false;
+ }
+ if (op == OP_WRITE) {
+ size_t size = 0;
+ unsigned char *ingress = pure_runtime_ingress(ticket, &size);
+ if (size != body_size || (size && (!ingress || pure_link_read(link, ingress, size, deadline) != 1)) ||
+ !pure_runtime_ready(ticket)) {
+ (void)pure_runtime_release(ticket);
+ return false;
+ }
+ }
+ PureOutcome outcome;
+ while (!pure_runtime_result(ticket, &outcome)) {
+ if (!pure_runtime_step(runtime)) { (void)pure_runtime_release(ticket); return false; }
+ }
+ bool sent = send_result(link, outcome, want_body, deadline);
+ (void)pure_runtime_release(ticket);
+ return sent;
+}
+static bool serve_connection(PureLink *link, PureRuntime *runtime, const unsigned char digest[32]) {
+ if (!write_hello(link, digest, pure_link_now_ms() + PURE_LINK_DEADLINE_MS)) return false;
+ int end = 0;
+ while (!end) if (!serve_request(link, runtime, &end)) return false;
+ return true;
+}
+static int serve(const char *bind_address, const char *port, const char *program_path,
+ const char *store_path, const char *ca, const char *cert,
+ const char *key, const char *client_name, unsigned max_connections) {
+ if (!pure_link_port_number(port, true) || !client_name || !*client_name) return 2;
+ PureProgram program;
+ unsigned char digest[32];
+ if (!load_program(program_path, &program, digest) || pure_store_init(store_path) != PURE_OK) return 2;
+ SSL_CTX *ctx = pure_link_context(true, ca, cert, key, alpn);
+ if (!ctx) { ERR_print_errors_fp(stderr); return 2; }
+ PureRuntime runtime;
+ PureWork work[1];
+ if (!pure_runtime_init(&runtime, work, 1, &program, pure_store_host(store_path),
+ 4u * 1024u * 1024u)) { SSL_CTX_free(ctx); return 2; }
+ int listener = pure_link_listen_at(bind_address, port);
+ if (listener < 0) { perror("listen"); SSL_CTX_free(ctx); return 2; }
+ struct sockaddr_storage address;
+ socklen_t address_size = sizeof(address);
+ if (getsockname(listener, (struct sockaddr *)&address, &address_size)) abort();
+ unsigned actual_port = address.ss_family == AF_INET
+ ? ntohs(((struct sockaddr_in *)&address)->sin_port)
+ : ntohs(((struct sockaddr_in6 *)&address)->sin6_port);
+ printf("READY %u\n", actual_port); fflush(stdout);
+ signal(SIGTERM, signal_stop); signal(SIGINT, signal_stop);
+ unsigned accepted = 0;
+ while (!stopping && (!max_connections || accepted < max_connections)) {
+ struct pollfd p = {.fd = listener, .events = POLLIN};
+ int result = poll(&p, 1, 1000);
+ if (result < 0) { if (errno == EINTR) continue; break; }
+ if (!result) continue;
+ int fd = accept(listener, NULL, NULL);
+ if (fd < 0) { if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) continue; break; }
+ ++accepted;
+ PureLink link = {.fd = fd};
+ bool healthy = pure_link_nonblocking(fd) &&
+ pure_link_handshake(&link, ctx, true, client_name, alpn);
+ if (healthy) healthy = serve_connection(&link, &runtime, digest);
+ pure_link_close(&link, healthy);
+ }
+ close(listener);
+ pure_runtime_stop(&runtime);
+ int status = runtime.active || runtime.retained ? 1 : 0;
+ SSL_CTX_free(ctx);
+ return status;
+}
+#ifndef PURE_PEER_SERVER_ONLY
+static int receive_result(PureLink *link, bool show, uint64_t deadline) {
+ unsigned char header[REPLY_BYTES];
+ if (pure_link_read(link, header, sizeof(header), deadline) != 1 ||
+ header[0] > PURE_ALLOCATION || get64(header + 1) > INT64_MAX ||
+ get32(header + 9) > PURE_OBJECT_LIMIT) return -1;
+ PureResult result = (PureResult)header[0];
+ int64_t revision = (int64_t)get64(header + 1);
+ uint32_t length = get32(header + 9);
+ if (result != PURE_OK && length) return -1;
+ unsigned char buffer[4096];
+ size_t left = show ? length : 0;
+ int failed = 0;
+ while (left) {
+ size_t count = left < sizeof(buffer) ? left : sizeof(buffer);
+ if (pure_link_read(link, buffer, count, deadline) != 1) return -1;
+ if (show && result == PURE_OK && fwrite(buffer, 1, count, stdout) != count) failed = 1;
+ left -= count;
+ }
+ if (result != PURE_OK) {
+ fprintf(stderr, "{\"status\":%u,\"revision\":\"%" PRId64 "\"}\n", result, revision);
+ return result == PURE_CONFLICT ? 3 : 2;
+ }
+ if (show) fprintf(stderr, "{\"revision\":\"%" PRId64 "\",\"bytes\":%u}\n", revision, length);
+ else if (printf("{\"revision\":\"%" PRId64 "\",\"reply_bytes\":%u}\n", revision, length) < 0) failed = 1;
+ if (fflush(stdout)) failed = 1;
+ return failed ? 2 : 0;
+}
+static int call(const char *host, const char *port, const char *server_name,
+ const char *program_path, const char *ca, const char *cert,
+ const char *key, int argc, char **argv) {
+ if (!pure_link_port_number(port, false) || !server_name || !*server_name || argc < 2) return 2;
+ bool show = !strcmp(argv[0], "show"), edit = !strcmp(argv[0], "edit");
+ if ((!show && !edit && strcmp(argv[0], "apply")) || argc != (show ? 2 : edit ? 6 : 4)) return 2;
+ PureProgram program;
+ unsigned char digest[32];
+ if (!load_program(program_path, &program, digest)) return 2;
+ size_t prefix = 0;
+ if (edit && !edit_layout(&program, &prefix)) return 2;
+ uint64_t expected = 0, offset = 0, remove = 0;
+ if (!show && !number(argv[2], INT64_MAX, &expected)) return 2;
+ if (edit && (!number(argv[3], UINT32_MAX, &offset) ||
+ !number(argv[4], UINT32_MAX, &remove))) return 2;
+ const char *document = argv[1];
+ size_t key_size = strlen(document);
+ if (!key_size || key_size > 64) return 2;
+ FILE *file = NULL;
+ size_t body_size = 0;
+ if (!show) {
+ file = fopen(argv[edit ? 5 : 3], "rb");
+ if (!file) { perror("input"); return 2; }
+ long bytes;
+ if (fseek(file, 0, SEEK_END) || (bytes = ftell(file)) < 0 ||
+ (uintmax_t)bytes > PURE_OBJECT_LIMIT - prefix || fseek(file, 0, SEEK_SET)) {
+ fclose(file); return 2;
+ }
+ body_size = prefix + (size_t)bytes;
+ }
+ SSL_CTX *ctx = pure_link_context(false, ca, cert, key, alpn);
+ if (!ctx) { if (file) fclose(file); ERR_print_errors_fp(stderr); return 2; }
+ PureLink link = {.fd = pure_link_connect_to(host, port)};
+ bool ready = link.fd >= 0 && pure_link_handshake(&link, ctx, false, server_name, alpn);
+ bool matched = ready && read_hello(&link, digest, pure_link_now_ms() + PURE_LINK_DEADLINE_MS);
+ if (!matched) {
+ fputs(ready ? "peer application definition mismatch\n" :
+ "peer authentication or connection failed\n", stderr);
+ pure_link_close(&link, false);
+ SSL_CTX_free(ctx);
+ if (file) fclose(file);
+ return 2;
+ }
+ int status = 2;
+ {
+ uint64_t deadline = pure_link_now_ms() + PURE_LINK_DEADLINE_MS;
+ unsigned char header[REQUEST_BYTES] = {0};
+ header[0] = (show ? OP_READ : OP_WRITE) | (show ? WANT_BODY : 0);
+ header[1] = (unsigned char)key_size;
+ put64(header + 2, expected);
+ put32(header + 10, (uint32_t)body_size);
+ ready = pure_link_write(&link, header, sizeof(header), deadline) &&
+ pure_link_write(&link, document, key_size, deadline);
+ if (ready && prefix) {
+ unsigned char fields[8] = {0};
+ put32le(fields + program.splice_offset.value, (uint32_t)offset);
+ put32le(fields + program.splice_remove.value, (uint32_t)remove);
+ ready = pure_link_write(&link, fields, prefix, deadline);
+ }
+ unsigned char buffer[4096];
+ size_t left = body_size - prefix;
+ while (ready && left) {
+ size_t count = left < sizeof(buffer) ? left : sizeof(buffer);
+ if (fread(buffer, 1, count, file) != count) { ready = false; break; }
+ ready = pure_link_write(&link, buffer, count, deadline);
+ left -= count;
+ }
+ if (file && (fgetc(file) != EOF || ferror(file))) ready = false;
+ if (ready) {
+ status = receive_result(&link, show, deadline);
+ if (status < 0) { status = 2; ready = false; }
+ }
+ }
+ if (!ready) fputs("peer failed or timed out; an interrupted write may have committed; query before retry\n", stderr);
+ pure_link_close(&link, ready);
+ SSL_CTX_free(ctx);
+ if (file && fclose(file)) status = 2;
+ return status;
+}
+#endif
+int main(int argc, char **argv) {
+ signal(SIGPIPE, SIG_IGN);
+#ifndef PURE_PEER_SERVER_ONLY
+ if (argc >= 11 && !strcmp(argv[1], "call"))
+ return call(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argc - 9, argv + 9);
+#endif
+ if ((argc == 10 || argc == 11) && !strcmp(argv[1], "serve")) {
+ uint64_t limit = 0;
+ if (argc == 11 && (!number(argv[10], UINT32_MAX, &limit) || !limit)) goto usage;
+ return serve(argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9],
+ (unsigned)limit);
+ }
+usage:
+ fputs("pure-document-peer serve BIND_IP PORT PROGRAM STORE_DIR CA.pem SERVER_CERT.pem SERVER_KEY.pem CLIENT_DNS [MAX_CONNECTIONS]\n", stderr);
+#ifndef PURE_PEER_SERVER_ONLY
+ fputs("pure-document-peer call HOST PORT SERVER_DNS PROGRAM CA.pem CLIENT_CERT.pem CLIENT_KEY.pem show KEY\n"
+ "pure-document-peer call HOST PORT SERVER_DNS PROGRAM CA.pem CLIENT_CERT.pem CLIENT_KEY.pem edit KEY REV OFFSET REMOVE INSERT_FILE\n"
+ "pure-document-peer call HOST PORT SERVER_DNS PROGRAM CA.pem CLIENT_CERT.pem CLIENT_KEY.pem apply KEY REV INPUT_FILE\n", stderr);
+#endif
+ return 2;
+}
diff --git a/prototypes/connections/edit-tui.c b/prototypes/connections/edit-tui.c
new file mode 100644
index 0000000..fbd73c1
--- /dev/null
+++ b/prototypes/connections/edit-tui.c
@@ -0,0 +1,945 @@
+#define _XOPEN_SOURCE 700
+/* O_NOFOLLOW is hidden by Darwin's strict X/Open namespace. */
+#ifdef __APPLE__
+#define _DARWIN_C_SOURCE
+#endif
+/* Optional terminal document editor. The program and store effect are the
+ * same ones used by the CLI and HTTP hosts; terminal state stays here. */
+#include "runtime.h"
+#include "store.h"
+#include "store-port.h"
+#ifdef PURE_EMBEDDED_PROGRAM
+#include "embedded-plan.h"
+#endif
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <unistd.h>
+#include <wchar.h>
+
+typedef struct {
+ char name[65];
+} DocumentKey;
+
+typedef struct {
+ PureRuntime runtime;
+ PureWork work[2];
+ const PureProgram *program;
+ const char *store;
+ char key[65], prompt[65], message[160];
+ unsigned char *text;
+ size_t capacity, gap_start, gap_end, scroll_row, prefix, prompt_size;
+ /* Logical byte position and its visual coordinate in anchor_columns. */
+ size_t anchor_position, anchor_row, anchor_column, anchor_columns;
+ DocumentKey *documents;
+ size_t document_count, document_selected, document_scroll;
+ int64_t revision;
+ bool exists, dirty, prompt_open, list_open, confirm_quit, confirm_reload, anchor_valid;
+ struct termios original_term;
+} Editor;
+
+static volatile sig_atomic_t stopping, resized, wake_write = -1;
+
+static void wake_signal(int signal_number) {
+ int saved_errno = errno;
+ if (signal_number == SIGWINCH) resized = 1;
+ else stopping = 1;
+ if (wake_write >= 0) {
+ const char byte = 1;
+ (void)write((int)wake_write, &byte, 1);
+ }
+ errno = saved_errno;
+}
+
+static bool valid_key(const char *key) {
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ unsigned char c = (unsigned char)key[i];
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || c == '_' || c == '-')) return false;
+ }
+ return true;
+}
+
+static int compare_document_key(const void *left, const void *right) {
+ return strcmp(((const DocumentKey *)left)->name, ((const DocumentKey *)right)->name);
+}
+
+static void close_list(Editor *editor) {
+ free(editor->documents);
+ editor->documents = NULL;
+ editor->document_count = editor->document_selected = editor->document_scroll = 0;
+ editor->prompt_size = 0;
+ editor->prompt[0] = 0;
+ editor->list_open = false;
+}
+
+/* Names are already sorted; find the first key with this prefix in-place. */
+static bool find_list_prefix(Editor *editor) {
+ if (!editor->prompt_size) return true;
+ size_t first = 0, end = editor->document_count;
+ while (first < end) {
+ size_t middle = first + (end - first) / 2;
+ if (strcmp(editor->documents[middle].name, editor->prompt) < 0) first = middle + 1;
+ else end = middle;
+ }
+ if (first == editor->document_count ||
+ strncmp(editor->documents[first].name, editor->prompt, editor->prompt_size)) return false;
+ editor->document_selected = first;
+ return true;
+}
+
+/* List names from the selected byte store, not from the execution core.
+ * Opening a name still goes through the store's checked READ path. Bound the
+ * optional browser to 8,192 names (520 KiB of key storage). */
+static bool open_list(Editor *editor) {
+ int descriptor = open(editor->store, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ DIR *directory = descriptor >= 0 ? fdopendir(descriptor) : NULL;
+ if (!directory) {
+ if (descriptor >= 0) close(descriptor);
+ snprintf(editor->message, sizeof(editor->message), "Could not read document directory");
+ return false;
+ }
+ DocumentKey *items = NULL;
+ size_t count = 0, capacity = 0;
+ bool complete = true;
+ for (;;) {
+ errno = 0;
+ struct dirent *entry = readdir(directory);
+ if (!entry) { if (errno) complete = false; break; }
+ if (strncmp(entry->d_name, "obj-", 4) || !valid_key(entry->d_name + 4)) continue;
+ if (count == 8192) { complete = false; break; }
+ if (count == capacity) {
+ size_t next = capacity ? capacity * 2 : 32;
+ DocumentKey *grown = realloc(items, next * sizeof(*grown));
+ if (!grown) { complete = false; break; }
+ items = grown;
+ capacity = next;
+ }
+ memcpy(items[count++].name, entry->d_name + 4, strlen(entry->d_name + 4) + 1);
+ }
+ if (closedir(directory)) complete = false;
+ if (!complete) {
+ free(items);
+ snprintf(editor->message, sizeof(editor->message), "Document list exceeds 8,192 keys or cannot be read");
+ return false;
+ }
+ if (count > 1) qsort(items, count, sizeof(*items), compare_document_key);
+ close_list(editor);
+ editor->documents = items;
+ editor->document_count = count;
+ for (size_t i = 0; i < count; ++i)
+ if (!strcmp(items[i].name, editor->key)) { editor->document_selected = i; break; }
+ editor->list_open = true;
+ return true;
+}
+
+static const char *result_name(PureResult result) {
+ switch (result) {
+ case PURE_NOT_FOUND: return "not found";
+ case PURE_CONFLICT: return "version conflict";
+ case PURE_BUSY: return "busy";
+ case PURE_BUDGET: return "request budget exceeded";
+ case PURE_LIMIT: return "document limit or invalid range";
+ case PURE_UNCERTAIN: return "durability unknown; inspect the stored revision before retrying";
+ case PURE_DENIED: return "operation denied";
+ case PURE_ALLOCATION: return "allocation failed";
+ default: return "operation failed";
+ }
+}
+
+static bool edit_layout(const PureProgram *program, size_t *prefix) {
+ if (!program->splice || !program->write.to_end || program->write_step ||
+ program->input_steps || !program->splice_offset.from_u32le ||
+ !program->splice_remove.from_u32le || program->read.offset ||
+ !program->read.to_end || program->read_required) return false;
+ size_t start = program->splice_offset.value, remove = program->splice_remove.value;
+ *prefix = program->write.offset;
+ if (*prefix > PURE_OBJECT_LIMIT || program->input_required > *prefix ||
+ start > *prefix || remove > *prefix || *prefix - start < 4 ||
+ *prefix - remove < 4) return false;
+ return start < remove ? remove - start >= 4 : start - remove >= 4;
+}
+
+static void put32(unsigned char *to, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) to[i] = (unsigned char)(value >> (8 * i));
+}
+
+static PureOutcome finish(Editor *editor, PureTicket ticket) {
+ PureOutcome result;
+ while (!pure_runtime_result(ticket, &result))
+ if (!pure_runtime_step(&editor->runtime)) return (PureOutcome){.status = PURE_INVALID};
+ return result;
+}
+
+static size_t length(const Editor *editor) {
+ return editor->capacity - (editor->gap_end - editor->gap_start);
+}
+
+static unsigned char byte_at(const Editor *editor, size_t index) {
+ return editor->text[index < editor->gap_start ? index :
+ index + editor->gap_end - editor->gap_start];
+}
+
+/* Skip printable ASCII directly within one side of the gap. Its terminal
+ * width is always one cell; UTF-8, controls and tabs use the glyph path. */
+static size_t plain_run(const Editor *editor, size_t position, size_t maximum) {
+ size_t available = position < editor->gap_start ? editor->gap_start - position
+ : length(editor) - position;
+ if (available > maximum) available = maximum;
+ const unsigned char *bytes = editor->text + (position < editor->gap_start
+ ? position : position + editor->gap_end - editor->gap_start);
+ size_t count = 0;
+ while (count < available && bytes[count] >= 32 && bytes[count] < 127) ++count;
+ return count;
+}
+
+static void advance_plain(size_t count, size_t columns, size_t *row, size_t *column) {
+ size_t cells = *column + count;
+ *row += cells / columns;
+ *column = cells % columns;
+}
+
+static void changed_at(Editor *editor, size_t position) {
+ if (editor->anchor_valid && position < editor->anchor_position)
+ editor->anchor_valid = false;
+}
+
+static void move_gap(Editor *editor, size_t position) {
+ if (position < editor->gap_start) {
+ size_t count = editor->gap_start - position;
+ memmove(editor->text + editor->gap_end - count, editor->text + position, count);
+ editor->gap_start -= count;
+ editor->gap_end -= count;
+ } else if (position > editor->gap_start) {
+ size_t count = position - editor->gap_start;
+ memmove(editor->text + editor->gap_start, editor->text + editor->gap_end, count);
+ editor->gap_start += count;
+ editor->gap_end += count;
+ }
+}
+
+static bool reserve_gap(Editor *editor, size_t needed) {
+ if (editor->gap_end - editor->gap_start >= needed) return true;
+ size_t used = length(editor);
+ if (needed > PURE_OBJECT_LIMIT - used) return false;
+ size_t target = editor->capacity * 2;
+ if (target < used + needed + 256) target = used + needed + 256;
+ if (target > PURE_OBJECT_LIMIT + 256) target = PURE_OBJECT_LIMIT + 256;
+ unsigned char *fresh = malloc(target);
+ if (!fresh) return false;
+ size_t right = editor->capacity - editor->gap_end;
+ memcpy(fresh, editor->text, editor->gap_start);
+ memcpy(fresh + target - right, editor->text + editor->gap_end, right);
+ free(editor->text);
+ editor->text = fresh;
+ editor->gap_end = target - right;
+ editor->capacity = target;
+ return true;
+}
+
+static bool insert_byte(Editor *editor, unsigned char byte) {
+ if (length(editor) >= PURE_OBJECT_LIMIT || !reserve_gap(editor, 1)) return false;
+ changed_at(editor, editor->gap_start);
+ editor->text[editor->gap_start++] = byte;
+ editor->dirty = true;
+ return true;
+}
+
+static size_t previous_codepoint(const Editor *editor, size_t position) {
+ if (!position) return 0;
+ --position;
+ while (position && (byte_at(editor, position) & 0xc0) == 0x80) --position;
+ return position;
+}
+
+static size_t next_codepoint(const Editor *editor, size_t position) {
+ size_t count = length(editor);
+ if (position == count) return count;
+ ++position;
+ while (position < count && (byte_at(editor, position) & 0xc0) == 0x80) ++position;
+ return position;
+}
+
+static bool valid_text_span(PureSpan span) {
+ for (size_t position = 0; position < span.size;) {
+ mbstate_t state = {0};
+ wchar_t character;
+ size_t used = mbrtowc(&character, (const char *)span.data + position,
+ span.size - position, &state);
+ if (used == (size_t)-1 || used == (size_t)-2 || !used ||
+ (character < 32 && character != L'\n' && character != L'\t') ||
+ character == 127 ||
+ (character != L'\n' && character != L'\t' && wcwidth(character) < 0)) return false;
+ position += used;
+ }
+ return true;
+}
+
+static bool read_document(Editor *editor, const char *key, bool require_existing) {
+ PureTicket ticket;
+ PureResult admitted = pure_runtime_accept(&editor->runtime, PURE_INPUT_READ,
+ key, 0, 0, &ticket);
+ if (admitted != PURE_OK) {
+ snprintf(editor->message, sizeof(editor->message), "Read rejected: %s", result_name(admitted));
+ return false;
+ }
+ PureOutcome result = finish(editor, ticket);
+ if (require_existing && result.status == PURE_NOT_FOUND) {
+ snprintf(editor->message, sizeof(editor->message), "Document disappeared; refresh the list");
+ pure_runtime_release(ticket);
+ return false;
+ }
+ if (result.status != PURE_OK && result.status != PURE_NOT_FOUND) {
+ snprintf(editor->message, sizeof(editor->message), "Read failed: %s", result_name(result.status));
+ pure_runtime_release(ticket);
+ return false;
+ }
+ size_t size = result.status == PURE_OK ? result.body.size : 0;
+ if (size > PURE_OBJECT_LIMIT || (size && !result.body.data) ||
+ !valid_text_span(result.body)) {
+ snprintf(editor->message, sizeof(editor->message), "Document is too large or is not plain UTF-8 text");
+ pure_runtime_release(ticket);
+ return false;
+ }
+ size_t capacity = size + 256;
+ unsigned char *fresh = malloc(capacity);
+ if (!fresh) {
+ snprintf(editor->message, sizeof(editor->message), "Could not allocate document buffer");
+ pure_runtime_release(ticket);
+ return false;
+ }
+ if (size) memcpy(fresh, result.body.data, size);
+ pure_runtime_release(ticket);
+ free(editor->text);
+ editor->text = fresh;
+ editor->capacity = capacity;
+ editor->gap_start = size;
+ editor->gap_end = capacity;
+ editor->scroll_row = 0;
+ editor->anchor_valid = false;
+ editor->revision = result.status == PURE_OK ? result.revision : 0;
+ editor->exists = result.status == PURE_OK;
+ editor->dirty = false;
+ editor->confirm_reload = false;
+ memcpy(editor->key, key, strlen(key) + 1);
+ snprintf(editor->message, sizeof(editor->message), "%s %zu bytes · revision %" PRId64,
+ editor->exists ? "Opened" : "New document", size, editor->revision);
+ return true;
+}
+
+static void save_document(Editor *editor) {
+ if (!editor->dirty && editor->exists) {
+ snprintf(editor->message, sizeof(editor->message), "No changes to save");
+ return;
+ }
+ PureTicket baseline;
+ PureResult admitted = pure_runtime_accept(&editor->runtime, PURE_INPUT_READ,
+ editor->key, 0, 0, &baseline);
+ if (admitted != PURE_OK) {
+ snprintf(editor->message, sizeof(editor->message), "Read rejected: %s", result_name(admitted));
+ return;
+ }
+ PureOutcome old = finish(editor, baseline);
+ if (old.status != PURE_OK && old.status != PURE_NOT_FOUND) {
+ snprintf(editor->message, sizeof(editor->message), "Could not inspect stored version: %s", result_name(old.status));
+ pure_runtime_release(baseline);
+ return;
+ }
+ int64_t stored_revision = old.status == PURE_OK ? old.revision : 0;
+ if (stored_revision != editor->revision) {
+ snprintf(editor->message, sizeof(editor->message), "Version conflict: stored %" PRId64 "; draft preserved",
+ stored_revision);
+ pure_runtime_release(baseline);
+ return;
+ }
+ size_t old_size = old.status == PURE_OK ? old.body.size : 0;
+ size_t draft_size = length(editor);
+ size_t prefix = 0;
+ while (prefix < old_size && prefix < draft_size &&
+ old.body.data[prefix] == byte_at(editor, prefix)) ++prefix;
+ while (prefix && prefix < old_size && (old.body.data[prefix] & 0xc0) == 0x80) --prefix;
+ size_t suffix = 0;
+ while (suffix < old_size - prefix && suffix < draft_size - prefix &&
+ old.body.data[old_size - suffix - 1] == byte_at(editor, draft_size - suffix - 1)) ++suffix;
+ while (suffix && (((old.body.data[old_size - suffix] & 0xc0) == 0x80) ||
+ ((byte_at(editor, draft_size - suffix) & 0xc0) == 0x80))) --suffix;
+ size_t remove = old_size - prefix - suffix;
+ size_t insert = draft_size - prefix - suffix;
+ if (!remove && !insert && editor->exists) {
+ editor->dirty = false;
+ snprintf(editor->message, sizeof(editor->message), "No changes to save");
+ pure_runtime_release(baseline);
+ return;
+ }
+ if (prefix > UINT32_MAX || remove > UINT32_MAX || insert > PURE_OBJECT_LIMIT - editor->prefix) {
+ snprintf(editor->message, sizeof(editor->message), "Edit exceeds selected program limit");
+ pure_runtime_release(baseline);
+ return;
+ }
+ PureTicket write_ticket;
+ admitted = pure_runtime_accept(&editor->runtime, PURE_INPUT_WRITE, editor->key,
+ editor->revision, editor->prefix + insert, &write_ticket);
+ if (admitted != PURE_OK) {
+ snprintf(editor->message, sizeof(editor->message), "Write rejected: %s", result_name(admitted));
+ pure_runtime_release(baseline);
+ return;
+ }
+ unsigned char *input = pure_runtime_ingress(write_ticket, NULL);
+ memset(input, 0, editor->prefix);
+ put32(input + editor->program->splice_offset.value, (uint32_t)prefix);
+ put32(input + editor->program->splice_remove.value, (uint32_t)remove);
+ for (size_t i = 0; i < insert; ++i) input[editor->prefix + i] = byte_at(editor, prefix + i);
+ pure_runtime_release(baseline);
+ if (!pure_runtime_ready(write_ticket)) {
+ pure_runtime_release(write_ticket);
+ snprintf(editor->message, sizeof(editor->message), "Could not publish edit");
+ return;
+ }
+ PureOutcome result = finish(editor, write_ticket);
+ pure_runtime_release(write_ticket);
+ if (result.status != PURE_OK) {
+ snprintf(editor->message, sizeof(editor->message), "Save failed: %s; draft preserved", result_name(result.status));
+ return;
+ }
+ editor->revision = result.revision;
+ editor->exists = true;
+ editor->dirty = false;
+ editor->confirm_quit = editor->confirm_reload = false;
+ snprintf(editor->message, sizeof(editor->message), "Saved %zu-byte edit at byte %zu · revision %" PRId64,
+ insert, prefix, result.revision);
+}
+
+static size_t glyph(const Editor *editor, size_t position, wchar_t *character,
+ int *width, char bytes[4], bool *valid) {
+ unsigned char first = byte_at(editor, position);
+ if (first < 128) {
+ bytes[0] = (char)first;
+ *character = (wchar_t)first;
+ *width = 1;
+ if ((first < 32 && first != '\n' && first != '\t') || first == 127 || !first) {
+ *valid = false;
+ bytes[0] = '?';
+ *character = L'?';
+ }
+ return 1;
+ }
+ size_t available = length(editor) - position;
+ if (available > 4) available = 4;
+ for (size_t i = 0; i < available; ++i) bytes[i] = (char)byte_at(editor, position + i);
+ mbstate_t state = {0};
+ size_t used = mbrtowc(character, bytes, available, &state);
+ if (used == (size_t)-1 || used == (size_t)-2 || !used ||
+ (*character < 32 && *character != L'\n' && *character != L'\t') ||
+ *character == 127) {
+ *valid = false;
+ *character = L'?';
+ *width = 1;
+ bytes[0] = '?';
+ return 1;
+ }
+ *width = wcwidth(*character);
+ if (*width < 0) {
+ *valid = false;
+ *character = L'?';
+ *width = 1;
+ bytes[0] = '?';
+ return 1;
+ }
+ return used;
+}
+
+static bool text_valid(const Editor *editor) {
+ for (size_t position = 0; position < length(editor);) {
+ wchar_t character;
+ int width;
+ char bytes[4];
+ bool valid = true;
+ size_t used = glyph(editor, position, &character, &width, bytes, &valid);
+ if (!valid) return false;
+ position += used;
+ }
+ return true;
+}
+
+static void advance(wchar_t character, int width, size_t columns,
+ size_t *row, size_t *column) {
+ if (character == L'\n') { ++*row; *column = 0; return; }
+ if (character == L'\t') width = 4 - (int)(*column % 4);
+ if (*column && *column + (size_t)width > columns) { ++*row; *column = 0; }
+ *column += (size_t)width;
+ if (*column >= columns) { ++*row; *column = 0; }
+}
+
+static void position_of(const Editor *editor, size_t target, size_t columns,
+ size_t *row, size_t *column) {
+ size_t position = 0;
+ *row = *column = 0;
+ if (editor->anchor_valid && editor->anchor_columns == columns &&
+ target >= editor->anchor_position) {
+ position = editor->anchor_position;
+ *row = editor->anchor_row;
+ *column = editor->anchor_column;
+ }
+ for (; position < target;) {
+ size_t run = plain_run(editor, position, target - position);
+ if (run) {
+ advance_plain(run, columns, row, column);
+ position += run;
+ continue;
+ }
+ wchar_t character;
+ int width;
+ char bytes[4];
+ bool valid = true;
+ size_t used = glyph(editor, position, &character, &width, bytes, &valid);
+ advance(character, width, columns, row, column);
+ position += used;
+ }
+}
+
+static size_t closest_position(const Editor *editor, size_t target_row,
+ size_t target_column, size_t columns) {
+ size_t row = 0, column = 0, position = 0, best = 0;
+ bool found = false;
+ if (editor->anchor_valid && editor->anchor_columns == columns &&
+ target_row > editor->anchor_row) {
+ row = editor->anchor_row;
+ column = editor->anchor_column;
+ position = editor->anchor_position;
+ }
+ for (; position < length(editor);) {
+ if (row == target_row && column <= target_column) { best = position; found = true; }
+ if (row > target_row || (row == target_row && column > target_column))
+ return found ? best : position;
+ wchar_t character;
+ int width;
+ char bytes[4];
+ bool valid = true;
+ size_t used = glyph(editor, position, &character, &width, bytes, &valid);
+ advance(character, width, columns, &row, &column);
+ position += used;
+ if (row == target_row && column <= target_column) { best = position; found = true; }
+ }
+ return found ? best : length(editor);
+}
+
+static void dimensions(size_t *rows, size_t *columns) {
+ struct winsize window = {0};
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &window) || !window.ws_row || !window.ws_col) {
+ *rows = 24; *columns = 80;
+ } else { *rows = window.ws_row; *columns = window.ws_col; }
+ if (*rows < 4) *rows = 4;
+ if (*columns < 8) *columns = 8;
+}
+
+static void draw_list(Editor *editor, size_t rows, size_t columns) {
+ size_t visible = rows - 3;
+ bool matching = editor->document_count && (!editor->prompt_size ||
+ !strncmp(editor->documents[editor->document_selected].name,
+ editor->prompt, editor->prompt_size));
+ if (editor->document_selected < editor->document_scroll)
+ editor->document_scroll = editor->document_selected;
+ if (editor->document_selected >= editor->document_scroll + visible)
+ editor->document_scroll = editor->document_selected - visible + 1;
+ fputs("\033[?25l\033[H\033[2J", stdout);
+ char header[80];
+ snprintf(header, sizeof(header), " Pure | documents | %zu keys", editor->document_count);
+ printf("%.*s", (int)columns, header);
+ for (size_t row = 0; row < visible && editor->document_scroll + row < editor->document_count; ++row) {
+ size_t index = editor->document_scroll + row;
+ printf("\033[%zu;1H%c %.*s", row + 2,
+ matching && index == editor->document_selected ? '>' : ' ',
+ (int)(columns - 2), editor->documents[index].name);
+ }
+ printf("\033[%zu;1H%.*s", rows - 1, (int)columns,
+ " Enter open Type to find Backspace clear Esc back");
+ char footer[230];
+ if (editor->prompt_size)
+ snprintf(footer, sizeof(footer), " Find: %.64s_ %.140s", editor->prompt,
+ matching ? editor->message : "No matching key");
+ else if (editor->document_count)
+ snprintf(footer, sizeof(footer), " %zu/%zu %s",
+ editor->document_selected + 1, editor->document_count, editor->message);
+ else snprintf(footer, sizeof(footer), " No stored documents; Ctrl+O creates a new key");
+ printf("\033[%zu;1H%.*s", rows, (int)columns, footer);
+ fflush(stdout);
+}
+
+static void draw(Editor *editor) {
+ size_t rows, columns;
+ dimensions(&rows, &columns);
+ if (editor->list_open) { draw_list(editor, rows, columns); return; }
+ if (editor->anchor_columns != columns) editor->anchor_valid = false;
+ size_t content_rows = rows - 3;
+ size_t cursor_row, cursor_column;
+ position_of(editor, editor->gap_start, columns, &cursor_row, &cursor_column);
+ if (cursor_row < editor->scroll_row) editor->scroll_row = cursor_row;
+ if (cursor_row >= editor->scroll_row + content_rows)
+ editor->scroll_row = cursor_row - content_rows + 1;
+ fputs("\033[?25l\033[H\033[2J", stdout);
+ char header[160];
+ snprintf(header, sizeof(header), " Pure | %s | revision %" PRId64 "%s | %zu bytes",
+ editor->key, editor->revision, editor->dirty ? " *" : "", length(editor));
+ printf("%.*s", (int)columns, header);
+ size_t row = 0, column = 0, position = 0, drawn_row = SIZE_MAX;
+ size_t anchor_row = editor->scroll_row > content_rows
+ ? editor->scroll_row - content_rows : 0;
+ bool keep_anchor = editor->anchor_valid && editor->anchor_row <= editor->scroll_row &&
+ editor->scroll_row - editor->anchor_row <= 2 * content_rows;
+ if (editor->anchor_valid && editor->anchor_row <= editor->scroll_row) {
+ row = editor->anchor_row;
+ column = editor->anchor_column;
+ position = editor->anchor_position;
+ }
+ if (!keep_anchor) editor->anchor_valid = false;
+ for (; position < length(editor);) {
+ if (!editor->anchor_valid && row >= anchor_row) {
+ editor->anchor_position = position;
+ editor->anchor_row = row;
+ editor->anchor_column = column;
+ editor->anchor_columns = columns;
+ editor->anchor_valid = true;
+ }
+ if (row >= editor->scroll_row + content_rows) break;
+ if (row < editor->scroll_row) {
+ size_t remaining = length(editor) - position;
+ size_t rows_to_view = editor->scroll_row - row;
+ size_t cells_to_view = rows_to_view > (remaining + column) / columns
+ ? remaining : rows_to_view * columns - column;
+ size_t run = plain_run(editor, position, cells_to_view);
+ if (run) {
+ advance_plain(run, columns, &row, &column);
+ position += run;
+ continue;
+ }
+ }
+ wchar_t character;
+ int width;
+ char bytes[4];
+ bool valid = true;
+ size_t used = glyph(editor, position, &character, &width, bytes, &valid);
+ size_t next_row = row, next_column = column;
+ size_t visible_width = character == L'\t' ? 4 - column % 4 : (size_t)width;
+ if (character != L'\n' && column && column + visible_width > columns) {
+ ++row;
+ column = 0;
+ }
+ if (row >= editor->scroll_row && row < editor->scroll_row + content_rows &&
+ character != L'\n') {
+ if (drawn_row != row) {
+ printf("\033[%zu;1H", row - editor->scroll_row + 2);
+ drawn_row = row;
+ }
+ if (character == L'\t') {
+ int spaces = 4 - (int)(column % 4);
+ while (spaces--) putchar(' ');
+ } else fwrite(bytes, 1, used, stdout);
+ }
+ row = next_row;
+ column = next_column;
+ advance(character, width, columns, &row, &column);
+ position += used;
+ }
+ printf("\033[%zu;1H%.*s", rows - 1, (int)columns,
+ " Ctrl+S save Ctrl+O open Ctrl+R reload Ctrl+Q quit arrows move");
+ char footer[230];
+ if (editor->prompt_open)
+ snprintf(footer, sizeof(footer), " Open key: %s_ (Enter to open, Esc to cancel)", editor->prompt);
+ else snprintf(footer, sizeof(footer), " %s", editor->message);
+ printf("\033[%zu;1H%.*s", rows, (int)columns, footer);
+ if (editor->prompt_open) {
+ size_t prompt_column = editor->prompt_size + strlen(" Open key: ") + 1;
+ if (prompt_column > columns) prompt_column = columns;
+ printf("\033[%zu;%zuH", rows, prompt_column);
+ } else printf("\033[%zu;%zuH", cursor_row - editor->scroll_row + 2,
+ cursor_column + 1);
+ fputs("\033[?25h", stdout);
+ fflush(stdout);
+}
+
+static int read_byte(int wake_read, int timeout_ms) {
+ struct pollfd fds[2] = {{.fd = STDIN_FILENO, .events = POLLIN},
+ {.fd = wake_read, .events = POLLIN}};
+ int ready = poll(fds, 2, timeout_ms);
+ if (ready < 0) return errno == EINTR ? -2 : -1;
+ if (!ready) return -3;
+ if (fds[1].revents) {
+ char buffer[32];
+ while (read(wake_read, buffer, sizeof(buffer)) > 0) { }
+ return -2;
+ }
+ unsigned char byte;
+ return read(STDIN_FILENO, &byte, 1) == 1 ? byte : -1;
+}
+
+static void move_vertical(Editor *editor, int delta) {
+ size_t rows, columns, row, column;
+ dimensions(&rows, &columns);
+ (void)rows;
+ position_of(editor, editor->gap_start, columns, &row, &column);
+ if (delta < 0 && !row) return;
+ move_gap(editor, closest_position(editor, delta < 0 ? row - 1 : row + 1,
+ column, columns));
+}
+
+static void handle_escape(Editor *editor, int wake_read) {
+ int a = read_byte(wake_read, 30);
+ if (a != '[') {
+ if (editor->list_open) close_list(editor);
+ editor->prompt_open = false;
+ return;
+ }
+ int b = read_byte(wake_read, 30);
+ if (editor->list_open) {
+ if (b == 'A' || b == 'B' || b == 'H' || b == 'F') {
+ editor->prompt_size = 0;
+ editor->prompt[0] = 0;
+ }
+ if (b == 'A' && editor->document_selected) --editor->document_selected;
+ else if (b == 'B' && editor->document_selected + 1 < editor->document_count)
+ ++editor->document_selected;
+ else if (b == 'H') editor->document_selected = 0;
+ else if (b == 'F' && editor->document_count)
+ editor->document_selected = editor->document_count - 1;
+ return;
+ }
+ if (b == 'A') move_vertical(editor, -1);
+ else if (b == 'B') move_vertical(editor, 1);
+ else if (b == 'C') move_gap(editor, next_codepoint(editor, editor->gap_start));
+ else if (b == 'D') move_gap(editor, previous_codepoint(editor, editor->gap_start));
+ else if (b == 'H') {
+ size_t position = editor->gap_start;
+ while (position && byte_at(editor, position - 1) != '\n') --position;
+ move_gap(editor, position);
+ } else if (b == 'F') {
+ size_t position = editor->gap_start;
+ while (position < length(editor) && byte_at(editor, position) != '\n') ++position;
+ move_gap(editor, position);
+ } else if (b == '3' && read_byte(wake_read, 30) == '~') {
+ size_t next = next_codepoint(editor, editor->gap_start);
+ if (next > editor->gap_start) {
+ changed_at(editor, editor->gap_start);
+ editor->gap_end += next - editor->gap_start;
+ editor->dirty = true;
+ }
+ }
+}
+
+static void handle_key(Editor *editor, int key, int wake_read) {
+ if (key < 0) return;
+ if (editor->prompt_open) {
+ if (key == 27) {
+ if (read_byte(wake_read, 30) == '[') {
+ int next = read_byte(wake_read, 30);
+ if (next >= '0' && next <= '9') (void)read_byte(wake_read, 30);
+ } else editor->prompt_open = false;
+ return;
+ }
+ if (key == 127 || key == 8) {
+ if (editor->prompt_size) editor->prompt[--editor->prompt_size] = 0;
+ return;
+ }
+ if (key == 13 || key == 10) {
+ if (valid_key(editor->prompt)) (void)read_document(editor, editor->prompt, false);
+ else snprintf(editor->message, sizeof(editor->message), "Key must be 1–64 ASCII letters, digits, _ or -");
+ editor->prompt_open = false;
+ return;
+ }
+ if (editor->prompt_size < 64 &&
+ ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') ||
+ (key >= '0' && key <= '9') || key == '_' || key == '-')) {
+ editor->prompt[editor->prompt_size++] = (char)key;
+ editor->prompt[editor->prompt_size] = 0;
+ }
+ return;
+ }
+ if (editor->list_open) {
+ if (key == 27) { handle_escape(editor, wake_read); return; }
+ if ((key == 127 || key == 8) && editor->prompt_size) {
+ editor->prompt[--editor->prompt_size] = 0;
+ (void)find_list_prefix(editor);
+ return;
+ }
+ if (editor->prompt_size < 64 &&
+ ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') ||
+ (key >= '0' && key <= '9') || key == '_' || key == '-')) {
+ editor->prompt[editor->prompt_size++] = (char)key;
+ editor->prompt[editor->prompt_size] = 0;
+ (void)find_list_prefix(editor);
+ return;
+ }
+ if ((key == 13 || key == 10) && editor->document_count &&
+ (!editor->prompt_size || !strncmp(editor->documents[editor->document_selected].name,
+ editor->prompt, editor->prompt_size))) {
+ if (read_document(editor, editor->documents[editor->document_selected].name, true))
+ close_list(editor);
+ return;
+ }
+ if (key == 12) { (void)open_list(editor); return; }
+ if (key == 15) close_list(editor);
+ else if (key != 17 && key != 3) return;
+ }
+ if (key == 17 || key == 3) {
+ if (editor->dirty && !editor->confirm_quit) {
+ editor->confirm_quit = true;
+ snprintf(editor->message, sizeof(editor->message), "Unsaved draft; press Ctrl+Q again to discard and quit");
+ } else stopping = 1;
+ return;
+ }
+ if (key != 18) editor->confirm_reload = false;
+ if (key != 17) editor->confirm_quit = false;
+ if (key == 19) { if (text_valid(editor)) save_document(editor);
+ else snprintf(editor->message, sizeof(editor->message), "Document contains invalid UTF-8 or control bytes");
+ return; }
+ if (key == 18) {
+ if (editor->dirty && !editor->confirm_reload) {
+ editor->confirm_reload = true;
+ snprintf(editor->message, sizeof(editor->message), "Unsaved draft; press Ctrl+R again to discard and reload");
+ } else (void)read_document(editor, editor->key, false);
+ return;
+ }
+ if (key == 15) {
+ if (editor->dirty) snprintf(editor->message, sizeof(editor->message), "Save or reload the draft before opening another key");
+ else { editor->prompt_open = true; editor->prompt_size = 0; editor->prompt[0] = 0; }
+ return;
+ }
+ if (key == 12) {
+ if (editor->dirty)
+ snprintf(editor->message, sizeof(editor->message), "Save or reload the draft before browsing documents");
+ else (void)open_list(editor);
+ return;
+ }
+ if (key == 27) { handle_escape(editor, wake_read); return; }
+ if (key == 127 || key == 8) {
+ size_t before = previous_codepoint(editor, editor->gap_start);
+ if (before < editor->gap_start) {
+ changed_at(editor, before);
+ editor->gap_start = before;
+ editor->dirty = true;
+ }
+ return;
+ }
+ if (key == 13) key = '\n';
+ if (key == '\n' || key == '\t' || key >= 32) {
+ if (!insert_byte(editor, (unsigned char)key))
+ snprintf(editor->message, sizeof(editor->message), "Document reached the byte limit");
+ }
+}
+
+static bool nonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
+}
+
+static bool raw_terminal(const struct termios *original) {
+ struct termios raw = *original;
+ raw.c_iflag &= (tcflag_t)~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ raw.c_oflag &= (tcflag_t)~OPOST;
+ raw.c_cflag |= CS8;
+ raw.c_lflag &= (tcflag_t)~(ECHO | ICANON | IEXTEN | ISIG);
+ raw.c_cc[VMIN] = 1;
+ raw.c_cc[VTIME] = 0;
+ return tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == 0;
+}
+
+int main(int argc, char **argv) {
+#ifdef PURE_EMBEDDED_PROGRAM
+ if (argc != 4 || strcmp(argv[1], "--store") || !valid_key(argv[3])) {
+ fputs("usage: pure-edit-tui-fixed --store DIRECTORY KEY\n", stderr);
+ return 2;
+ }
+ const char *store_path = argv[2], *key = argv[3];
+ const PureProgram *program = &pure_embedded_program;
+#else
+ if (argc != 6 || strcmp(argv[1], "--program") || strcmp(argv[3], "--store") ||
+ !valid_key(argv[5])) {
+ fputs("usage: pure-edit-tui --program FILE --store DIRECTORY KEY\n", stderr);
+ return 2;
+ }
+ const char *store_path = argv[4], *key = argv[5];
+ PureProgram loaded;
+ char error[160];
+ if (!pure_program_load(argv[2], &loaded, error, sizeof(error))) {
+ fprintf(stderr, "Program: %s\n", error);
+ return 2;
+ }
+ const PureProgram *program = &loaded;
+#endif
+ size_t prefix;
+ if (!edit_layout(program, &prefix)) {
+ fputs("Program needs a complete-document read and two u32le splice fields with trailing insertion bytes\n", stderr);
+ return 2;
+ }
+ if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) {
+ fputs("terminal editor requires a TTY\n", stderr);
+ return 2;
+ }
+ setlocale(LC_CTYPE, "");
+ Editor editor = {.store = store_path, .program = program, .prefix = prefix};
+ if (pure_store_init(editor.store) != PURE_OK ||
+ !pure_runtime_init(&editor.runtime, editor.work, 2, program,
+ pure_store_host(editor.store), 4u * 1024u * 1024u) ||
+ !read_document(&editor, key, false)) {
+ fprintf(stderr, "Could not open document: %s\n", editor.message);
+ free(editor.text);
+ return 2;
+ }
+ int wake[2];
+ if (pipe(wake) || !nonblocking(wake[0]) || !nonblocking(wake[1]) ||
+ tcgetattr(STDIN_FILENO, &editor.original_term)) {
+ perror("terminal setup");
+ free(editor.text);
+ return 2;
+ }
+ wake_write = wake[1];
+ struct sigaction action = {.sa_handler = wake_signal};
+ sigemptyset(&action.sa_mask);
+ if (sigaction(SIGINT, &action, NULL) || sigaction(SIGTERM, &action, NULL) ||
+ sigaction(SIGWINCH, &action, NULL)) {
+ perror("sigaction");
+ wake_write = -1;
+ close(wake[0]);
+ close(wake[1]);
+ free(editor.text);
+ return 2;
+ }
+ if (!raw_terminal(&editor.original_term)) {
+ perror("raw terminal");
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &editor.original_term);
+ wake_write = -1;
+ close(wake[0]);
+ close(wake[1]);
+ free(editor.text);
+ return 2;
+ }
+ fputs("\033[?1049h", stdout);
+ while (!stopping) {
+ draw(&editor);
+ int key = read_byte(wake[0], -1);
+ if (resized) resized = 0;
+ if (key == -1) { stopping = 1; break; }
+ handle_key(&editor, key, wake[0]);
+ }
+ fputs("\033[?25h\033[?1049l", stdout);
+ fflush(stdout);
+ wake_write = -1;
+ close(wake[0]);
+ close(wake[1]);
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &editor.original_term);
+ pure_runtime_stop(&editor.runtime);
+ close_list(&editor);
+ free(editor.text);
+ return 0;
+}
diff --git a/prototypes/connections/edit-window.c b/prototypes/connections/edit-window.c
new file mode 100644
index 0000000..303b2bf
--- /dev/null
+++ b/prototypes/connections/edit-window.c
@@ -0,0 +1,638 @@
+#define _POSIX_C_SOURCE 200809L
+/* Optional GTK document adapter for the same prepared edit program used by
+ * pure-edit and pure-connections. GTK text lives at the application boundary;
+ * Pure's execution core remains independent of the UI and document encoding. */
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <gtk/gtk.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef struct {
+ PureProgram program;
+ PureRuntime runtime;
+ PureWork work[1];
+ const char *directory, *program_path;
+ char key[65];
+ size_t prefix, baseline_size;
+ char *baseline;
+ char *definition_baseline;
+ size_t definition_baseline_size;
+ uint64_t definition_generation;
+ size_t last_output_bytes;
+ bool has_edit_output;
+ bool definition_needs_apply;
+ int64_t revision;
+ bool exists;
+ bool closing, asking_to_close;
+ GtkWidget *window, *text, *status, *version, *heading, *key_entry;
+ GtkWidget *source, *source_revealer, *source_status;
+} Editor;
+
+static const char *result_name(PureResult result) {
+ switch (result) {
+ case PURE_OK: return "ok";
+ case PURE_NOT_FOUND: return "not found";
+ case PURE_CONFLICT: return "version conflict";
+ case PURE_BUSY: return "busy";
+ case PURE_BUDGET: return "request budget exceeded";
+ case PURE_LIMIT: return "document limit or invalid range";
+ case PURE_UNCERTAIN: return "durability unknown; inspect the stored revision before retrying";
+ case PURE_DENIED: return "operation denied";
+ case PURE_ALLOCATION: return "allocation failed";
+ default: return "operation failed";
+ }
+}
+
+static bool valid_key(const char *key) {
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ char c = key[i];
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || c == '_' || c == '-')) return false;
+ }
+ return true;
+}
+
+/* The window supplies the convenience layout accepted by pure-edit. The
+ * prepared program, not the window, determines the splice field locations. */
+static bool edit_layout(const PureProgram *p, size_t *prefix) {
+ if (!p->splice || !p->write.to_end || p->write_step || p->input_steps ||
+ !p->splice_offset.from_u32le || !p->splice_remove.from_u32le ||
+ p->read.offset || !p->read.to_end || p->read_required) return false;
+ size_t start = p->splice_offset.value, remove = p->splice_remove.value;
+ *prefix = p->write.offset;
+ if (*prefix > PURE_OBJECT_LIMIT || p->input_required > *prefix || start > *prefix ||
+ remove > *prefix || *prefix - start < 4 || *prefix - remove < 4) return false;
+ return start < remove ? remove - start >= 4 : start - remove >= 4;
+}
+
+static void put32(unsigned char *to, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) to[i] = (unsigned char)(value >> (8 * i));
+}
+
+static void status(Editor *e, const char *text) {
+ gtk_label_set_text(GTK_LABEL(e->status), text);
+ char revision[64];
+ snprintf(revision, sizeof(revision), "%s · revision %" PRId64,
+ e->exists ? "Stored" : "New", e->revision);
+ gtk_label_set_text(GTK_LABEL(e->version), revision);
+}
+
+static void definition_status(Editor *e, const char *text) {
+ gtk_label_set_text(GTK_LABEL(e->source_status), text);
+}
+
+static void definition_title(Editor *e) {
+ char title[128];
+ if (e->has_edit_output)
+ snprintf(title, sizeof(title), "%s · Pure document · definition %" PRIu64
+ " · output %zu B", e->key, e->definition_generation, e->last_output_bytes);
+ else snprintf(title, sizeof(title), "%s · Pure document · definition %" PRIu64,
+ e->key, e->definition_generation);
+ gtk_window_set_title(GTK_WINDOW(e->window), title);
+}
+
+static void apply_definition(Editor *e) {
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->source));
+ GtkTextIter first, last;
+ gtk_text_buffer_get_bounds(buffer, &first, &last);
+ char *draft = gtk_text_buffer_get_text(buffer, &first, &last, FALSE);
+ size_t length = strlen(draft);
+ bool changed = length != e->definition_baseline_size ||
+ memcmp(draft, e->definition_baseline, length) != 0;
+ if (!changed && !e->definition_needs_apply) {
+ gtk_text_buffer_set_modified(buffer, FALSE);
+ definition_status(e, "No definition changes to apply");
+ g_free(draft);
+ return;
+ }
+ PureProgram candidate;
+ size_t prefix = 0;
+ char error[160] = {0};
+ if (length > PURE_PROGRAM_LIMIT ||
+ !pure_program_parse(draft, length, &candidate, error, sizeof(error)) ||
+ !edit_layout(&candidate, &prefix)) {
+ char message[240];
+ snprintf(message, sizeof(message), "Definition rejected: %s; draft preserved",
+ error[0] ? error : "document edit/read contract required");
+ definition_status(e, message);
+ g_free(draft);
+ return;
+ }
+ char *on_disk = NULL;
+ gsize on_disk_size = 0;
+ GError *file_error = NULL;
+ bool read = g_file_get_contents(e->program_path, &on_disk, &on_disk_size, &file_error);
+ bool same = read && on_disk_size == e->definition_baseline_size &&
+ !memcmp(on_disk, e->definition_baseline, on_disk_size);
+ g_free(on_disk);
+ if (file_error) g_error_free(file_error);
+ if (!same) {
+ definition_status(e, "Definition changed on disk; draft preserved. Reload or resolve it first");
+ g_free(draft);
+ return;
+ }
+ if (e->runtime.active || e->runtime.running) {
+ definition_status(e, "A document operation is active; definition draft preserved");
+ g_free(draft);
+ return;
+ }
+ if (changed && !g_file_set_contents_full(e->program_path, draft, (gssize)length,
+ G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_DURABLE, 0600, &file_error)) {
+ char message[240];
+ snprintf(message, sizeof(message), "Could not save definition: %s; draft preserved",
+ file_error ? file_error->message : "unknown error");
+ definition_status(e, message);
+ if (file_error) g_error_free(file_error);
+ g_free(draft);
+ return;
+ }
+ PureProgram previous = e->program;
+ size_t previous_prefix = e->prefix;
+ e->program = candidate;
+ e->prefix = prefix;
+ if (!pure_runtime_restart(&e->runtime, &e->program,
+ pure_store_host(e->directory), 4u * 1024u * 1024u)) {
+ e->program = previous;
+ e->prefix = previous_prefix;
+ bool restored = !changed || g_file_set_contents_full(e->program_path, e->definition_baseline,
+ (gssize)e->definition_baseline_size,
+ G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_DURABLE, 0600, NULL);
+ definition_status(e, restored ? "Could not install definition; previous source restored" :
+ "Definition installation failed; inspect source file before retrying");
+ g_free(draft);
+ return;
+ }
+ g_free(e->definition_baseline);
+ e->definition_baseline = draft;
+ e->definition_baseline_size = length;
+ gtk_text_buffer_set_modified(buffer, FALSE);
+ e->definition_needs_apply = false;
+ ++e->definition_generation;
+ e->has_edit_output = false;
+ definition_title(e);
+ definition_status(e, "Applied locally & saved; other hosts load it after restart");
+}
+
+static void apply_definition_clicked(GtkButton *button, gpointer data) {
+ (void)button;
+ apply_definition(data);
+}
+
+static void reload_definition(Editor *e) {
+ char *source = NULL;
+ gsize length = 0;
+ GError *error = NULL;
+ if (!g_file_get_contents(e->program_path, &source, &length, &error) ||
+ length > PURE_PROGRAM_LIMIT || memchr(source, 0, length) ||
+ !g_utf8_validate(source, (gssize)length, NULL)) {
+ definition_status(e, "Could not load a UTF-8 definition within 16 KiB; draft preserved");
+ if (error) g_error_free(error);
+ g_free(source);
+ return;
+ }
+ g_free(e->definition_baseline);
+ e->definition_baseline = source;
+ e->definition_baseline_size = length;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->source));
+ gtk_text_buffer_set_text(buffer, source, (int)length);
+ gtk_text_buffer_set_modified(buffer, FALSE);
+ e->definition_needs_apply = true;
+ definition_status(e, "Definition reloaded from disk; Apply to run it");
+}
+
+static void reload_definition_clicked(GtkButton *button, gpointer data) {
+ (void)button;
+ Editor *e = data;
+ if (gtk_text_buffer_get_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->source)))) {
+ definition_status(e, "Definition draft has changes; use Discard & reload");
+ return;
+ }
+ reload_definition(e);
+}
+
+static void discard_definition_clicked(GtkButton *button, gpointer data) {
+ (void)button;
+ reload_definition(data);
+}
+
+static void toggle_definition(Editor *e) {
+ bool shown = gtk_revealer_get_reveal_child(GTK_REVEALER(e->source_revealer));
+ gtk_revealer_set_reveal_child(GTK_REVEALER(e->source_revealer), !shown);
+ gtk_widget_grab_focus(shown ? e->text : e->source);
+}
+
+static void toggle_definition_clicked(GtkButton *button, gpointer data) {
+ (void)button;
+ toggle_definition(data);
+}
+
+static PureOutcome finish(Editor *e, PureTicket ticket) {
+ PureOutcome result;
+ while (!pure_runtime_result(ticket, &result))
+ if (!pure_runtime_step(&e->runtime)) return (PureOutcome){.status = PURE_INVALID};
+ return result;
+}
+
+static bool open_document_key(Editor *e, const char *key) {
+ PureTicket ticket;
+ PureResult accepted = pure_runtime_accept(&e->runtime, PURE_INPUT_READ,
+ key, 0, 0, &ticket);
+ if (accepted != PURE_OK) { status(e, result_name(accepted)); return false; }
+ PureOutcome result = finish(e, ticket);
+ char *copy = NULL;
+ if (result.status == PURE_OK) {
+ if (result.body.size > G_MAXINT ||
+ (result.body.size && (!result.body.data ||
+ memchr(result.body.data, 0, result.body.size) ||
+ !g_utf8_validate((const char *)result.body.data, result.body.size, NULL)))) {
+ pure_runtime_release(ticket);
+ status(e, "Stored bytes are not plain UTF-8 text; use pure-edit for binary data");
+ return false;
+ }
+ copy = g_malloc(result.body.size + 1);
+ if (result.body.size) memcpy(copy, result.body.data, result.body.size);
+ copy[result.body.size] = 0;
+ }
+ pure_runtime_release(ticket);
+ if (result.status != PURE_OK && result.status != PURE_NOT_FOUND) {
+ status(e, result_name(result.status));
+ return false;
+ }
+ if (strcmp(key, e->key) != 0) memcpy(e->key, key, strlen(key) + 1);
+ g_free(e->baseline);
+ e->baseline = copy ? copy : g_strdup("");
+ e->baseline_size = result.status == PURE_OK ? result.body.size : 0;
+ e->revision = result.status == PURE_OK ? result.revision : 0;
+ e->exists = result.status == PURE_OK;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->text));
+ gtk_text_buffer_set_text(buffer, e->baseline, (int)e->baseline_size);
+ gtk_text_buffer_set_modified(buffer, FALSE);
+ e->has_edit_output = false;
+ gtk_label_set_text(GTK_LABEL(e->heading), e->key);
+ definition_title(e);
+ char message[128];
+ snprintf(message, sizeof(message), "%s · %zu bytes", e->exists ? "Loaded" : "New document",
+ e->baseline_size);
+ status(e, message);
+ return true;
+}
+
+static void open_document(Editor *e) {
+ (void)open_document_key(e, e->key);
+}
+
+static void open_key(Editor *e) {
+ GtkTextBuffer *document = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->text));
+ GtkTextBuffer *definition = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->source));
+ if (gtk_text_buffer_get_modified(document) || gtk_text_buffer_get_modified(definition)) {
+ status(e, "Save or discard the document and definition drafts before opening another key");
+ return;
+ }
+ const char *key = gtk_editable_get_text(GTK_EDITABLE(e->key_entry));
+ if (!valid_key(key)) { status(e, "Key must be 1–64 ASCII letters, digits, _ or -"); return; }
+ if (open_document_key(e, key)) gtk_widget_grab_focus(e->text);
+}
+
+static void open_key_clicked(GtkButton *button, gpointer data) {
+ (void)button;
+ open_key(data);
+}
+
+static void open_key_activated(GtkEntry *entry, gpointer data) {
+ (void)entry;
+ open_key(data);
+}
+
+static void reload_clicked(GtkButton *button, gpointer data) {
+ (void)button;
+ Editor *e = data;
+ if (gtk_text_buffer_get_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->text)))) {
+ status(e, "Draft has changes; use Discard & reload to replace it");
+ return;
+ }
+ open_document(e);
+}
+
+static void discard_clicked(GtkButton *button, gpointer data) {
+ (void)button;
+ open_document(data);
+}
+
+static bool continuation(unsigned char c) { return (c & 0xc0u) == 0x80u; }
+
+/* Find the smallest changed byte interval with valid UTF-8 boundaries. The
+ * storage effect still sees bytes; this only keeps the UI's edit interval
+ * meaningful when two code points happen to share leading/trailing bytes. */
+static void change_span(const char *old, size_t old_size, const char *draft, size_t draft_size,
+ size_t *start, size_t *remove, size_t *insert) {
+ size_t prefix = 0;
+ while (prefix < old_size && prefix < draft_size && old[prefix] == draft[prefix]) ++prefix;
+ while (prefix && prefix < old_size && continuation((unsigned char)old[prefix])) --prefix;
+ size_t suffix = 0;
+ while (suffix < old_size - prefix && suffix < draft_size - prefix &&
+ old[old_size - suffix - 1] == draft[draft_size - suffix - 1]) ++suffix;
+ while (suffix && (continuation((unsigned char)old[old_size - suffix]) ||
+ continuation((unsigned char)draft[draft_size - suffix]))) --suffix;
+ *start = prefix;
+ *remove = old_size - prefix - suffix;
+ *insert = draft_size - prefix - suffix;
+}
+
+static void save_document(Editor *e) {
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->text));
+ GtkTextIter first, last;
+ gtk_text_buffer_get_bounds(buffer, &first, &last);
+ char *draft = gtk_text_buffer_get_text(buffer, &first, &last, FALSE);
+ size_t draft_size = strlen(draft);
+ size_t offset, remove, insert;
+ change_span(e->baseline, e->baseline_size, draft, draft_size, &offset, &remove, &insert);
+ if (e->exists && !remove && !insert) {
+ gtk_text_buffer_set_modified(buffer, FALSE);
+ status(e, "No changes to save");
+ g_free(draft);
+ return;
+ }
+ if (draft_size > PURE_OBJECT_LIMIT || offset > UINT32_MAX || remove > UINT32_MAX ||
+ insert > PURE_OBJECT_LIMIT - e->prefix) {
+ status(e, "Document or edit exceeds the selected byte limit");
+ g_free(draft);
+ return;
+ }
+ PureTicket ticket;
+ PureResult accepted = pure_runtime_accept(&e->runtime, PURE_INPUT_WRITE, e->key,
+ e->revision, e->prefix + insert, &ticket);
+ if (accepted != PURE_OK) {
+ status(e, result_name(accepted));
+ g_free(draft);
+ return;
+ }
+ unsigned char *input = pure_runtime_ingress(ticket, NULL);
+ memset(input, 0, e->prefix);
+ put32(input + e->program.splice_offset.value, (uint32_t)offset);
+ put32(input + e->program.splice_remove.value, (uint32_t)remove);
+ if (insert) memcpy(input + e->prefix, draft + offset, insert);
+ if (!pure_runtime_ready(ticket)) {
+ pure_runtime_release(ticket);
+ status(e, "Could not publish edit");
+ g_free(draft);
+ return;
+ }
+ PureOutcome result = finish(e, ticket);
+ size_t reply_size = result.body.size;
+ pure_runtime_release(ticket);
+ if (result.status != PURE_OK) {
+ char message[160];
+ if (result.status == PURE_CONFLICT)
+ snprintf(message, sizeof(message), "Version conflict: stored revision %" PRId64
+ "; draft preserved", result.revision);
+ else snprintf(message, sizeof(message), "%s; draft preserved", result_name(result.status));
+ status(e, message);
+ g_free(draft);
+ return;
+ }
+ g_free(e->baseline);
+ e->baseline = draft;
+ e->baseline_size = draft_size;
+ e->revision = result.revision;
+ e->exists = true;
+ e->last_output_bytes = reply_size;
+ e->has_edit_output = true;
+ definition_title(e);
+ gtk_text_buffer_set_modified(buffer, FALSE);
+ char message[128];
+ snprintf(message, sizeof(message), "Saved %zu-byte edit at byte %zu · output %zu bytes",
+ insert, offset, reply_size);
+ status(e, message);
+}
+
+static void save_clicked(GtkButton *button, gpointer data) {
+ (void)button;
+ save_document(data);
+}
+
+static gboolean key_pressed(GtkEventControllerKey *controller, guint keyval, guint keycode,
+ GdkModifierType modifiers, gpointer data) {
+ (void)controller; (void)keycode;
+ Editor *e = data;
+ if ((modifiers & GDK_CONTROL_MASK) && (modifiers & GDK_SHIFT_MASK) &&
+ (keyval == GDK_KEY_d || keyval == GDK_KEY_D)) {
+ toggle_definition(e);
+ return TRUE;
+ }
+ if ((modifiers & GDK_CONTROL_MASK) &&
+ (keyval == GDK_KEY_o || keyval == GDK_KEY_O)) {
+ gtk_widget_grab_focus(e->key_entry);
+ return TRUE;
+ }
+ if ((modifiers & GDK_CONTROL_MASK) &&
+ (keyval == GDK_KEY_s || keyval == GDK_KEY_S)) {
+ if ((modifiers & GDK_SHIFT_MASK) ||
+ gtk_window_get_focus(GTK_WINDOW(e->window)) == e->source)
+ apply_definition(e);
+ else save_document(e);
+ return TRUE;
+ }
+ if ((modifiers & GDK_CONTROL_MASK) &&
+ (keyval == GDK_KEY_w || keyval == GDK_KEY_W)) {
+ gtk_window_close(GTK_WINDOW(e->window));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void close_decision(GObject *source, GAsyncResult *response, gpointer data) {
+ Editor *e = data;
+ GError *error = NULL;
+ int selected = gtk_alert_dialog_choose_finish(GTK_ALERT_DIALOG(source), response, &error);
+ if (error) g_error_free(error);
+ e->asking_to_close = false;
+ if (selected == 1) {
+ e->closing = true;
+ gtk_window_destroy(GTK_WINDOW(e->window));
+ }
+}
+
+static gboolean close_requested(GtkWindow *window, gpointer data) {
+ Editor *e = data;
+ bool document_changed = gtk_text_buffer_get_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->text)));
+ bool definition_changed = gtk_text_buffer_get_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->source)));
+ if (e->closing || (!document_changed && !definition_changed))
+ return FALSE;
+ if (e->asking_to_close) return TRUE;
+ e->asking_to_close = true;
+ GtkAlertDialog *dialog = gtk_alert_dialog_new("Discard unsaved document or definition changes?");
+ gtk_alert_dialog_set_detail(dialog, "The current draft has not been saved or applied.");
+ const char *buttons[] = {"Keep editing", "Discard changes", NULL};
+ gtk_alert_dialog_set_buttons(dialog, buttons);
+ gtk_alert_dialog_set_cancel_button(dialog, 0);
+ gtk_alert_dialog_set_default_button(dialog, 0);
+ gtk_alert_dialog_choose(dialog, window, NULL, close_decision, e);
+ g_object_unref(dialog);
+ return TRUE;
+}
+
+static void activate(GtkApplication *application, gpointer data) {
+ Editor *e = data;
+ if (e->window) { gtk_window_present(GTK_WINDOW(e->window)); return; }
+ e->window = gtk_application_window_new(application);
+ g_signal_connect(e->window, "close-request", G_CALLBACK(close_requested), e);
+ gtk_window_set_default_size(GTK_WINDOW(e->window), 960, 680);
+ definition_title(e);
+ GtkWidget *column = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_window_set_child(GTK_WINDOW(e->window), column);
+ GtkWidget *bar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
+ gtk_widget_set_margin_start(bar, 14);
+ gtk_widget_set_margin_end(bar, 14);
+ gtk_widget_set_margin_top(bar, 12);
+ gtk_widget_set_margin_bottom(bar, 12);
+ gtk_box_append(GTK_BOX(column), bar);
+ e->heading = gtk_label_new(e->key);
+ gtk_widget_add_css_class(e->heading, "title-3");
+ gtk_box_append(GTK_BOX(bar), e->heading);
+ e->version = gtk_label_new("");
+ gtk_widget_add_css_class(e->version, "dim-label");
+ gtk_box_append(GTK_BOX(bar), e->version);
+ GtkWidget *spacer = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_hexpand(spacer, TRUE);
+ gtk_box_append(GTK_BOX(bar), spacer);
+ GtkWidget *definition = gtk_button_new_with_label("Definition · Ctrl+Shift+D");
+ g_signal_connect(definition, "clicked", G_CALLBACK(toggle_definition_clicked), e);
+ gtk_box_append(GTK_BOX(bar), definition);
+ GtkWidget *reload = gtk_button_new_with_label("Reload");
+ g_signal_connect(reload, "clicked", G_CALLBACK(reload_clicked), e);
+ gtk_box_append(GTK_BOX(bar), reload);
+ GtkWidget *discard = gtk_button_new_with_label("Discard & reload");
+ g_signal_connect(discard, "clicked", G_CALLBACK(discard_clicked), e);
+ gtk_box_append(GTK_BOX(bar), discard);
+ GtkWidget *save = gtk_button_new_with_label("Save · Ctrl+S");
+ gtk_widget_add_css_class(save, "suggested-action");
+ g_signal_connect(save, "clicked", G_CALLBACK(save_clicked), e);
+ gtk_box_append(GTK_BOX(bar), save);
+ GtkWidget *scroll = gtk_scrolled_window_new();
+ gtk_widget_set_vexpand(scroll, TRUE);
+ gtk_box_append(GTK_BOX(column), scroll);
+ e->text = gtk_text_view_new();
+ gtk_accessible_update_property(GTK_ACCESSIBLE(e->text),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, "Document text", -1);
+ gtk_text_view_set_monospace(GTK_TEXT_VIEW(e->text), TRUE);
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(e->text), GTK_WRAP_WORD_CHAR);
+ gtk_widget_set_margin_start(e->text, 18);
+ gtk_widget_set_margin_end(e->text, 18);
+ gtk_widget_set_margin_top(e->text, 12);
+ gtk_widget_set_margin_bottom(e->text, 12);
+ gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(scroll), e->text);
+ e->source_revealer = gtk_revealer_new();
+ gtk_box_append(GTK_BOX(column), e->source_revealer);
+ GtkWidget *source_panel = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
+ gtk_widget_set_margin_start(source_panel, 14);
+ gtk_widget_set_margin_end(source_panel, 14);
+ gtk_widget_set_margin_bottom(source_panel, 8);
+ gtk_revealer_set_child(GTK_REVEALER(e->source_revealer), source_panel);
+ GtkWidget *source_bar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_box_append(GTK_BOX(source_panel), source_bar);
+ GtkWidget *source_heading = gtk_label_new("Application definition · editor.pure");
+ gtk_widget_add_css_class(source_heading, "title-4");
+ gtk_box_append(GTK_BOX(source_bar), source_heading);
+ GtkWidget *source_spacer = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_hexpand(source_spacer, TRUE);
+ gtk_box_append(GTK_BOX(source_bar), source_spacer);
+ GtkWidget *source_reload = gtk_button_new_with_label("Reload definition");
+ g_signal_connect(source_reload, "clicked", G_CALLBACK(reload_definition_clicked), e);
+ gtk_box_append(GTK_BOX(source_bar), source_reload);
+ GtkWidget *source_discard = gtk_button_new_with_label("Discard & reload");
+ g_signal_connect(source_discard, "clicked", G_CALLBACK(discard_definition_clicked), e);
+ gtk_box_append(GTK_BOX(source_bar), source_discard);
+ GtkWidget *source_apply = gtk_button_new_with_label("Apply & save · Ctrl+S");
+ gtk_widget_add_css_class(source_apply, "suggested-action");
+ g_signal_connect(source_apply, "clicked", G_CALLBACK(apply_definition_clicked), e);
+ gtk_box_append(GTK_BOX(source_bar), source_apply);
+ GtkWidget *source_scroll = gtk_scrolled_window_new();
+ gtk_widget_set_size_request(source_scroll, -1, 260);
+ gtk_box_append(GTK_BOX(source_panel), source_scroll);
+ e->source = gtk_text_view_new();
+ gtk_accessible_update_property(GTK_ACCESSIBLE(e->source),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, "Application definition source", -1);
+ gtk_text_view_set_monospace(GTK_TEXT_VIEW(e->source), TRUE);
+ gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(source_scroll), e->source);
+ GtkTextBuffer *source_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(e->source));
+ gtk_text_buffer_set_text(source_buffer, e->definition_baseline,
+ (int)e->definition_baseline_size);
+ gtk_text_buffer_set_modified(source_buffer, FALSE);
+ e->source_status = gtk_label_new("Definition is active; edit and apply to change it");
+ gtk_label_set_xalign(GTK_LABEL(e->source_status), 0);
+ gtk_box_append(GTK_BOX(source_panel), e->source_status);
+ GtkWidget *footer = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
+ gtk_widget_set_margin_start(footer, 14);
+ gtk_widget_set_margin_end(footer, 14);
+ gtk_widget_set_margin_top(footer, 9);
+ gtk_widget_set_margin_bottom(footer, 11);
+ gtk_box_append(GTK_BOX(column), footer);
+ e->status = gtk_label_new("");
+ gtk_label_set_xalign(GTK_LABEL(e->status), 0);
+ gtk_widget_set_hexpand(e->status, TRUE);
+ gtk_box_append(GTK_BOX(footer), e->status);
+ e->key_entry = gtk_entry_new();
+ gtk_entry_set_max_length(GTK_ENTRY(e->key_entry), 64);
+ gtk_editable_set_text(GTK_EDITABLE(e->key_entry), e->key);
+ gtk_entry_set_placeholder_text(GTK_ENTRY(e->key_entry), "Document key");
+ gtk_editable_set_width_chars(GTK_EDITABLE(e->key_entry), 15);
+ gtk_accessible_update_property(GTK_ACCESSIBLE(e->key_entry),
+ GTK_ACCESSIBLE_PROPERTY_LABEL, "Document key", -1);
+ g_signal_connect(e->key_entry, "activate", G_CALLBACK(open_key_activated), e);
+ gtk_box_append(GTK_BOX(footer), e->key_entry);
+ GtkWidget *open = gtk_button_new_with_label("Open · Ctrl+O");
+ g_signal_connect(open, "clicked", G_CALLBACK(open_key_clicked), e);
+ gtk_box_append(GTK_BOX(footer), open);
+ GtkEventController *keys = gtk_event_controller_key_new();
+ g_signal_connect(keys, "key-pressed", G_CALLBACK(key_pressed), e);
+ gtk_widget_add_controller(e->window, keys);
+ open_document(e);
+ gtk_window_present(GTK_WINDOW(e->window));
+}
+
+int main(int argc, char **argv) {
+ if (argc != 6 || strcmp(argv[1], "--program") || strcmp(argv[3], "--store") ||
+ !valid_key(argv[5])) {
+ fputs("pure-edit-window --program FILE --store DIRECTORY KEY\n", stderr);
+ return 2;
+ }
+ Editor e = {.directory = argv[4], .program_path = argv[2], .definition_generation = 1};
+ memcpy(e.key, argv[5], strlen(argv[5]) + 1);
+ char error[160] = {0};
+ gsize source_size = 0;
+ GError *source_error = NULL;
+ if (!g_file_get_contents(e.program_path, &e.definition_baseline, &source_size, &source_error) ||
+ source_size > PURE_PROGRAM_LIMIT ||
+ memchr(e.definition_baseline, 0, source_size) ||
+ !g_utf8_validate(e.definition_baseline, (gssize)source_size, NULL) ||
+ !pure_program_parse(e.definition_baseline, source_size, &e.program, error, sizeof(error)) ||
+ !edit_layout(&e.program, &e.prefix)) {
+ fprintf(stderr, "Program must define the simple splice edit layout: %s\n",
+ error[0] ? error : source_error ? source_error->message : "unsupported layout");
+ if (source_error) g_error_free(source_error);
+ g_free(e.definition_baseline);
+ return 2;
+ }
+ e.definition_baseline_size = source_size;
+ if (pure_store_init(e.directory) != PURE_OK ||
+ !pure_runtime_init(&e.runtime, e.work, 1, &e.program,
+ pure_store_host(e.directory), 4u * 1024u * 1024u)) {
+ fputs("Cannot initialize document store or execution domain\n", stderr);
+ return 2;
+ }
+ e.baseline = g_strdup("");
+ GtkApplication *application = gtk_application_new("org.pure.DocumentEditor", G_APPLICATION_NON_UNIQUE);
+ g_signal_connect(application, "activate", G_CALLBACK(activate), &e);
+ char *app_argv[] = {argv[0], NULL};
+ int result = g_application_run(G_APPLICATION(application), 1, app_argv);
+ g_object_unref(application);
+ g_free(e.baseline);
+ g_free(e.definition_baseline);
+ return result;
+}
diff --git a/prototypes/connections/edit.c b/prototypes/connections/edit.c
new file mode 100644
index 0000000..7c070e4
--- /dev/null
+++ b/prototypes/connections/edit.c
@@ -0,0 +1,177 @@
+#define _POSIX_C_SOURCE 200809L
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef PURE_EMBEDDED_PROGRAM
+#include "embedded-plan.h"
+#endif
+
+/* Native automation entry for the same prepared document program as the
+ * network adapter. No socket or body serialization in the local execution. */
+static bool number(const char *text, uint64_t limit, uint64_t *out) {
+ if (!*text) return false;
+ uint64_t value = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > limit || value > (limit - digit) / 10) return false;
+ value = value * 10 + digit;
+ }
+ *out = value;
+ return true;
+}
+
+static const char *message(PureResult status) {
+ switch (status) {
+ case PURE_OK: return "ok";
+ case PURE_NOT_FOUND: return "not_found";
+ case PURE_CONFLICT: return "conflict";
+ case PURE_BUSY: return "busy";
+ case PURE_BUDGET: return "payload_budget";
+ case PURE_LIMIT: return "limit";
+ case PURE_UNCERTAIN: return "durability_unknown";
+ case PURE_DENIED: return "denied";
+ case PURE_ALLOCATION: return "allocation";
+ case PURE_INVALID: return "invalid";
+ default: return "failed";
+ }
+}
+
+static void put32(unsigned char *to, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) to[i] = (unsigned char)(value >> (8 * i));
+}
+
+/* The convenience command fills the program's two numeric splice arguments
+ * and its trailing insertion bytes. A more general input uses apply. */
+static bool edit_layout(const PureProgram *p, size_t *prefix) {
+ if (!p->splice || !p->write.to_end || p->write_step || p->input_steps ||
+ !p->splice_offset.from_u32le || !p->splice_remove.from_u32le) return false;
+ size_t start = p->splice_offset.value, remove = p->splice_remove.value;
+ *prefix = p->write.offset;
+ if (*prefix > PURE_OBJECT_LIMIT || p->input_required > *prefix || start > *prefix ||
+ remove > *prefix || *prefix - start < 4 || *prefix - remove < 4) return false;
+ return start < remove ? remove - start >= 4 : start - remove >= 4;
+}
+
+int main(int argc, char **argv) {
+#ifndef PURE_EMBEDDED_PROGRAM
+ const char *program_path = NULL, *store_path = NULL;
+#else
+ const char *store_path = NULL;
+#endif
+ size_t budget = 4u * 1024u * 1024u;
+ int at = 1;
+ for (; at + 1 < argc && !strncmp(argv[at], "--", 2); at += 2) {
+ uint64_t value;
+ if (!strcmp(argv[at], "--store")) store_path = argv[at + 1];
+#ifndef PURE_EMBEDDED_PROGRAM
+ else if (!strcmp(argv[at], "--program")) program_path = argv[at + 1];
+#endif
+ else if (!strcmp(argv[at], "--budget") && number(argv[at + 1], SIZE_MAX, &value)) budget = (size_t)value;
+ else goto usage;
+ }
+#ifndef PURE_EMBEDDED_PROGRAM
+ if (!program_path) goto usage;
+#endif
+ if (!store_path || at >= argc) goto usage;
+ bool show = !strcmp(argv[at], "show"), edit = !strcmp(argv[at], "edit");
+ if ((!show && !edit && strcmp(argv[at], "apply")) ||
+ argc - at != (show ? 2 : edit ? 6 : 4)) goto usage;
+ uint64_t expected = 0, offset = 0, remove = 0;
+ if (!show && !number(argv[at + 2], INT64_MAX, &expected)) goto usage;
+ if (edit && (!number(argv[at + 3], UINT32_MAX, &offset) || !number(argv[at + 4], UINT32_MAX, &remove))) goto usage;
+#ifndef PURE_EMBEDDED_PROGRAM
+ PureProgram loaded;
+ char error[160];
+ if (!pure_program_load(program_path, &loaded, error, sizeof(error))) {
+ fprintf(stderr, "Program: %s\n", error); return 2;
+ }
+ const PureProgram *program = &loaded;
+#else
+ const PureProgram *program = &pure_embedded_program;
+#endif
+ size_t prefix = 0;
+ if (edit && !edit_layout(program, &prefix)) {
+ fputs("edit requires two distinct u32le splice fields and trailing insertion bytes; use apply for a custom input\n", stderr);
+ return 2;
+ }
+ FILE *file = NULL;
+ size_t length = 0;
+ if (!show) {
+ file = fopen(argv[at + (edit ? 5 : 3)], "rb");
+ if (!file) { perror("input"); return 2; }
+ long bytes;
+ if (fseek(file, 0, SEEK_END) || (bytes = ftell(file)) < 0 ||
+ (uintmax_t)bytes > PURE_OBJECT_LIMIT - prefix || fseek(file, 0, SEEK_SET)) {
+ fputs("input must be a seekable file within the request size limit\n", stderr);
+ fclose(file); return 2;
+ }
+ length = (size_t)bytes;
+ }
+ if (pure_store_init(store_path) != PURE_OK) {
+ if (file) fclose(file);
+ fputs("cannot initialize store\n", stderr); return 2;
+ }
+ PureRuntime runtime;
+ PureWork work[1];
+ if (!pure_runtime_init(&runtime, work, 1, program, pure_store_host(store_path), budget)) {
+ if (file) fclose(file);
+ return 2;
+ }
+ PureTicket ticket;
+ PureResult admitted = pure_runtime_accept(&runtime, show ? PURE_INPUT_READ : PURE_INPUT_WRITE,
+ argv[at + 1], (int64_t)expected, prefix + length, &ticket);
+ if (admitted != PURE_OK) {
+ if (file) fclose(file);
+ fprintf(stderr, "%s\n", message(admitted)); return 2;
+ }
+ if (!show) {
+ unsigned char *input = pure_runtime_ingress(ticket, NULL);
+ if (prefix) memset(input, 0, prefix);
+ if (edit) {
+ put32(input + program->splice_offset.value, (uint32_t)offset);
+ put32(input + program->splice_remove.value, (uint32_t)remove);
+ }
+ bool valid = !length || fread(input + prefix, 1, length, file) == length;
+ if (fgetc(file) != EOF || ferror(file)) valid = false;
+ if (fclose(file)) valid = false;
+ if (!valid) {
+ pure_runtime_release(ticket);
+ fputs("input changed or could not be read; nothing was applied\n", stderr); return 2;
+ }
+ if (!pure_runtime_ready(ticket)) { pure_runtime_release(ticket); return 2; }
+ }
+ PureOutcome outcome;
+ while (!pure_runtime_result(ticket, &outcome)) {
+ if (!pure_runtime_step(&runtime)) { pure_runtime_release(ticket); return 2; }
+ }
+ int status = 0;
+ if (outcome.status != PURE_OK) {
+ fprintf(stderr, "{\"error\":\"%s\",\"revision\":\"%" PRId64 "\"}\n", message(outcome.status), outcome.revision);
+ status = outcome.status == PURE_CONFLICT ? 3 : 2;
+ } else if (show) {
+ if (outcome.body.size && fwrite(outcome.body.data, 1, outcome.body.size, stdout) != outcome.body.size) status = 2;
+ fprintf(stderr, "{\"revision\":\"%" PRId64 "\",\"bytes\":%zu}\n", outcome.revision, outcome.body.size);
+ } else {
+ if (printf("{\"revision\":\"%" PRId64 "\",\"reply_bytes\":%zu}\n", outcome.revision, outcome.body.size) < 0) status = 2;
+ }
+ if (fflush(stdout)) status = 2;
+ pure_runtime_release(ticket);
+ return status;
+usage:
+ fputs(
+#ifdef PURE_EMBEDDED_PROGRAM
+ "pure-edit-fixed --store DIRECTORY [--budget BYTES] show KEY\n"
+ "pure-edit-fixed --store DIRECTORY [--budget BYTES] edit KEY REVISION BYTE_OFFSET REMOVE_BYTES INSERT_FILE\n"
+ "pure-edit-fixed --store DIRECTORY [--budget BYTES] apply KEY REVISION INPUT_FILE\n"
+#else
+ "pure-edit --program FILE --store DIRECTORY [--budget BYTES] show KEY\n"
+ "pure-edit --program FILE --store DIRECTORY [--budget BYTES] edit KEY REVISION BYTE_OFFSET REMOVE_BYTES INSERT_FILE\n"
+ "pure-edit --program FILE --store DIRECTORY [--budget BYTES] apply KEY REVISION INPUT_FILE\n"
+#endif
+ "edit uses the prepared program's field locations; apply accepts its raw input bytes.\n", stderr);
+ return 2;
+}
diff --git a/prototypes/connections/evaluate.c b/prototypes/connections/evaluate.c
new file mode 100644
index 0000000..88ffae7
--- /dev/null
+++ b/prototypes/connections/evaluate.c
@@ -0,0 +1,53 @@
+#include "program.h"
+#include <stdint.h>
+
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out) {
+ *out = (PureSpan){0};
+ if (region.offset > source.size) return false;
+ size_t length = region.to_end ? source.size - region.offset : region.length;
+ if (length > source.size - region.offset) return false;
+ *out = (PureSpan){length ? source.data + region.offset : NULL, length};
+ return true;
+}
+
+static bool index_read(PureIndex index, PureSpan source, size_t *out) {
+ if (!index.from_u32le) { *out = index.value; return true; }
+ if (index.value > source.size || 4 > source.size - index.value) return false;
+ const unsigned char *bytes = source.data + index.value;
+ *out = (size_t)bytes[0] | (size_t)bytes[1] << 8 | (size_t)bytes[2] << 16 | (size_t)bytes[3] << 24;
+ return true;
+}
+
+bool pure_program_splice(const PureProgram *p, PureSpan source, size_t *offset, size_t *remove) {
+ return p->splice && index_read(p->splice_offset, source, offset) &&
+ index_read(p->splice_remove, source, remove);
+}
+
+static bool resolve(PureRegion region, size_t step, PureSpan source,
+ const PureSpan *values, size_t count, PureSpan *out) {
+ if (!step) return pure_region_span(region, source, out);
+ if (step > count) return false;
+ *out = values[step - 1];
+ return true;
+}
+
+bool pure_program_input(const PureProgram *p, PureSpan source, PureSpan *write, PureSpan *reply) {
+ *write = (PureSpan){0};
+ *reply = (PureSpan){0};
+ if (source.size < p->input_required || p->input_steps > PURE_DYNAMIC_LIMIT) return false;
+ PureSpan values[PURE_DYNAMIC_LIMIT];
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ PureSpan parent;
+ size_t offset, length;
+ if (!resolve(step->source, step->source_step, source, values, i, &parent) ||
+ !index_read(step->offset, source, &offset) || !index_read(step->length, source, &length) ||
+ !pure_region_span((PureRegion){.offset = offset, .length = length}, parent, &values[i])) return false;
+ }
+ PureSpan stored, returned = {0};
+ if (!resolve(p->write, p->write_step, source, values, p->input_steps, &stored) ||
+ (p->reply_input && !resolve(p->reply, p->reply_step, source, values, p->input_steps, &returned))) return false;
+ *write = stored;
+ *reply = returned;
+ return true;
+}
diff --git a/prototypes/connections/examples/bounded-editor.pure b/prototypes/connections/examples/bounded-editor.pure
new file mode 100644
index 0000000..e9f2634
--- /dev/null
+++ b/prototypes/connections/examples/bounded-editor.pure
@@ -0,0 +1,19 @@
+// Same document edit as editor.pure, with an authored final-size policy.
+// The store checks the limit against the current version under its writer lock.
+layout Edit {
+ start: u32le;
+ remove: u32le;
+ insert: bytes;
+}
+
+on get {
+ let document = store.read(request.key);
+ reply(document, document.body);
+}
+
+on put {
+ let edit = view(Edit, request.body);
+ let saved = store.splice(request.key, request.revision,
+ edit.start, edit.remove, edit.insert, 8);
+ reply(saved, edit.insert);
+}
diff --git a/prototypes/connections/examples/editor.pure b/prototypes/connections/examples/editor.pure
new file mode 100644
index 0000000..4de78bc
--- /dev/null
+++ b/prototypes/connections/examples/editor.pure
@@ -0,0 +1,19 @@
+// A revision-checked byte edit. The input carries only the replacement.
+// UTF-8 cursor/grapheme positions are translated to byte ranges by the UI.
+layout Edit {
+ start: u32le;
+ remove: u32le;
+ insert: bytes;
+}
+
+on get {
+ let document = store.read(request.key);
+ reply(document, document.body);
+}
+
+on put {
+ let edit = view(Edit, request.body);
+ let saved = store.splice(request.key, request.revision,
+ edit.start, edit.remove, edit.insert);
+ reply(saved, edit.insert);
+}
diff --git a/prototypes/connections/examples/excerpt.pure b/prototypes/connections/examples/excerpt.pure
new file mode 100644
index 0000000..622f9bb
--- /dev/null
+++ b/prototypes/connections/examples/excerpt.pure
@@ -0,0 +1,13 @@
+// Read bytes 32..47 of an object that must contain the complete 64-byte window.
+// Preparation keeps the size check for 16..79, and maps only 32..47 for reply.
+on get {
+ let object = store.read(request.key);
+ let window = range(object.body, 16, 64);
+ let excerpt = range(window, 16, 16);
+ reply(object, excerpt);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/examples/select-text.py b/prototypes/connections/examples/select-text.py
new file mode 100644
index 0000000..ffaf80b
--- /dev/null
+++ b/prototypes/connections/examples/select-text.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+"""Save a UTF-8 document selection through selection.pure (character indices)."""
+import argparse
+import http.client
+import json
+from pathlib import Path
+import re
+import struct
+from urllib.parse import urlsplit
+
+LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('file', type=Path)
+ parser.add_argument('--key', required=True)
+ parser.add_argument('--start', type=int, required=True, help='first Unicode code point, starting at 0')
+ parser.add_argument('--end', type=int, required=True, help='exclusive Unicode code point boundary')
+ parser.add_argument('--revision', type=int, default=0, help='0 creates; otherwise expected stored revision')
+ parser.add_argument('--url', default='http://127.0.0.1:8767')
+ args = parser.parse_args()
+ url = urlsplit(args.url)
+ try:
+ port = url.port or 80
+ except ValueError as error:
+ parser.error(str(error))
+ if (url.scheme != 'http' or url.hostname not in ['localhost', '127.0.0.1'] or
+ url.username is not None or url.password is not None or url.path not in ['', '/'] or
+ url.query or url.fragment):
+ parser.error('use a local HTTP server origin')
+ if not re.fullmatch(r'[A-Za-z0-9_-]{1,64}', args.key) or not 0 <= args.revision <= 2**63 - 1:
+ parser.error('invalid object key or revision')
+ try:
+ with args.file.open('rb') as source:
+ document = source.read(LIMIT - 8 + 1)
+ if len(document) > LIMIT - 8:
+ parser.error('document exceeds the prototype request limit')
+ text = document.decode('utf-8')
+ except (OSError, UnicodeError) as error:
+ parser.error(str(error))
+ if not 0 <= args.start <= args.end <= len(text):
+ parser.error('selection is outside the document')
+ start = len(text[:args.start].encode('utf-8'))
+ selected = text[args.start:args.end].encode('utf-8')
+ # The boundary layout is explicit; storage receives only selected bytes.
+ payload = struct.pack('<II', start, len(selected)) + document
+ headers = {'Content-Type': 'application/octet-stream'}
+ headers['If-None-Match' if args.revision == 0 else 'If-Match'] = (
+ '*' if args.revision == 0 else f'"{args.revision}"')
+ connection = http.client.HTTPConnection(url.hostname, port, timeout=12)
+ try:
+ connection.request('PUT', '/objects/' + args.key, payload, headers)
+ response = connection.getresponse()
+ body = response.read(LIMIT + 1)
+ if response.status != 200:
+ parser.error(f'storage response {response.status}: {response.getheader("X-Pure-Error")}')
+ if body != selected:
+ parser.error('response differs from the selection; check the installed program (write may have occurred)')
+ revision = response.getheader('ETag', '')
+ if not re.fullmatch(r'"[1-9][0-9]*"', revision) or int(revision[1:-1]) > 2**63 - 1:
+ parser.error('response has no valid stored revision (write may have occurred)')
+ except (OSError, http.client.HTTPException) as error:
+ parser.error(f'{error}; storage outcome is unknown if the request was sent')
+ finally:
+ connection.close()
+ print(json.dumps({'revision': revision[1:-1], 'selected': selected.decode('utf-8'),
+ 'stored_bytes': len(selected)}, ensure_ascii=False))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/examples/selection.pure b/prototypes/connections/examples/selection.pure
new file mode 100644
index 0000000..7d9d4ec
--- /dev/null
+++ b/prototypes/connections/examples/selection.pure
@@ -0,0 +1,19 @@
+// This is an input boundary layout, not a required storage or RAM model.
+// The client sends two little-endian u32 values followed by document bytes.
+layout Selection {
+ start: u32le;
+ count: u32le;
+ document: bytes;
+}
+
+on get {
+ let saved = store.read(request.key);
+ reply(saved, saved.body);
+}
+
+on put {
+ let input = view(Selection, request.body);
+ let selected = range(input.document, input.start, input.count);
+ let saved = store.write(request.key, request.revision, selected);
+ reply(saved, selected);
+}
diff --git a/prototypes/connections/examples/storage.pure b/prototypes/connections/examples/storage.pure
new file mode 100644
index 0000000..ff54ea3
--- /dev/null
+++ b/prototypes/connections/examples/storage.pure
@@ -0,0 +1,11 @@
+// The host supplies request bytes, an object name, and the expected revision.
+// Failed storage results propagate to the host's response without executing reply.
+on get {
+ let object = store.read(request.key);
+ reply(object, object.body);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/export_flat_store.py b/prototypes/connections/export_flat_store.py
new file mode 100644
index 0000000..9469d5a
--- /dev/null
+++ b/prototypes/connections/export_flat_store.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python3
+"""Export the selected paged document store to a new default-format store."""
+import argparse
+import fcntl
+import hashlib
+import json
+import os
+from pathlib import Path
+import re
+import shutil
+import subprocess
+import tempfile
+
+KEY = re.compile(r'[A-Za-z0-9_-]{1,64}\Z')
+LIMIT = (2 * 6 + 32) * 32768 + 8192
+FLAGS = os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW | os.O_CLOEXEC
+
+
+def show(binary, store, key):
+ result = subprocess.run([str(binary), '--store', str(store), 'show', key],
+ capture_output=True, timeout=30)
+ if result.returncode:
+ raise RuntimeError(f'{binary.name} could not read {key}: {result.stderr[-400:]!r}')
+ details = json.loads(result.stderr)
+ revision = int(details['revision'])
+ body = result.stdout
+ if not 1 <= revision <= (1 << 63) - 1 or len(body) != details['bytes'] or len(body) > LIMIT:
+ raise RuntimeError(f'invalid stored document: {key}')
+ return revision, body
+
+
+def write_all(fd, content):
+ content = memoryview(content)
+ while content:
+ written = os.write(fd, content)
+ if written <= 0:
+ raise OSError('short store write')
+ content = content[written:]
+
+
+def export(source, destination, paged_editor, flat_editor):
+ source = source.resolve(strict=True)
+ if os.path.lexists(destination):
+ raise ValueError('destination must not exist, including a symlink')
+ destination = destination.resolve(strict=False)
+ if (not source.is_dir() or source == destination or source in destination.parents or
+ os.path.lexists(destination)):
+ raise ValueError('source must be a directory and destination must be a new separate path')
+ parent = destination.parent.resolve(strict=True)
+ if not parent.is_dir():
+ raise ValueError('destination parent must already exist')
+ lock = os.open(source / '.writer.lock', os.O_RDONLY | os.O_NOFOLLOW | os.O_CLOEXEC)
+ stage = None
+ try:
+ # A separate CLI process reads each object; its lock-file close cannot
+ # release this parent's POSIX read lock. Cooperating writers get BUSY.
+ try:
+ fcntl.lockf(lock, fcntl.LOCK_SH | fcntl.LOCK_NB)
+ except BlockingIOError as error:
+ raise RuntimeError('source has an active writer; retry export') from error
+ keys = []
+ with os.scandir(source) as entries:
+ for entry in entries:
+ if not entry.name.startswith('obj-'):
+ continue
+ key = entry.name[4:]
+ if not KEY.fullmatch(key) or not entry.is_file(follow_symlinks=False):
+ raise RuntimeError(f'invalid object entry: {entry.name}')
+ keys.append(key)
+ stage = Path(tempfile.mkdtemp(prefix=f'.{destination.name}.export-', dir=parent))
+ stage_fd = os.open(stage, FLAGS)
+ digest = hashlib.sha256()
+ total = 0
+ try:
+ marker = os.open('.writer.lock', os.O_CREAT | os.O_EXCL | os.O_WRONLY |
+ os.O_NOFOLLOW | os.O_CLOEXEC, 0o600, dir_fd=stage_fd)
+ try:
+ os.fsync(marker)
+ finally:
+ os.close(marker)
+ for key in sorted(keys):
+ revision, body = show(paged_editor, source, key)
+ name = 'obj-' + key
+ fd = os.open(name, os.O_CREAT | os.O_EXCL | os.O_WRONLY |
+ os.O_NOFOLLOW | os.O_CLOEXEC, 0o600, dir_fd=stage_fd)
+ try:
+ header = b'PUREB001' + revision.to_bytes(8, 'little') + len(body).to_bytes(8, 'little')
+ write_all(fd, header)
+ write_all(fd, body)
+ os.fsync(fd)
+ finally:
+ os.close(fd)
+ if show(flat_editor, stage, key) != (revision, body):
+ raise RuntimeError(f'flat readback differs: {key}')
+ digest.update(key.encode('ascii') + b'\0')
+ digest.update(header[8:])
+ digest.update(body)
+ total += len(body)
+ os.fsync(stage_fd)
+ finally:
+ os.close(stage_fd)
+ if os.path.lexists(destination):
+ raise FileExistsError(destination)
+ os.rename(stage, destination)
+ stage = None
+ parent_fd = os.open(parent, FLAGS)
+ try:
+ os.fsync(parent_fd)
+ finally:
+ os.close(parent_fd)
+ return {'objects': len(keys), 'logical_bytes': total,
+ 'document_digest': digest.hexdigest(),
+ 'paged_reader_sha256': hashlib.sha256(paged_editor.read_bytes()).hexdigest(),
+ 'flat_reader_sha256': hashlib.sha256(flat_editor.read_bytes()).hexdigest()}
+ finally:
+ if stage is not None:
+ shutil.rmtree(stage)
+ os.close(lock)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--source', type=Path, required=True)
+ parser.add_argument('--destination', type=Path, required=True)
+ parser.add_argument('--paged-editor', type=Path, required=True,
+ help='fixed editor linked with store-paged.c')
+ parser.add_argument('--flat-editor', type=Path, required=True,
+ help='fixed editor linked with the default store.c')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ result = export(args.source, args.destination,
+ args.paged_editor.resolve(strict=True), args.flat_editor.resolve(strict=True))
+ body = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(body)
+ print(body, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/fixed-budget.json b/prototypes/connections/fixed-budget.json
new file mode 100644
index 0000000..35439be
--- /dev/null
+++ b/prototypes/connections/fixed-budget.json
@@ -0,0 +1,18 @@
+{
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "binaries": {
+ "pure-edit-fixed": {
+ "max_text_bytes": 20480,
+ "max_data_bytes": 1000,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ },
+ "pure-connections-fixed": {
+ "max_text_bytes": 26880,
+ "max_data_bytes": 1100,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ }
+ },
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The HTTP ceiling includes the reviewed 188-byte cost of moving document interpretation from the reusable core into the selected document adapter and the later 64-byte linked increase for an authored final-size guard. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files."
+}
diff --git a/prototypes/connections/fixed-package-budget.json b/prototypes/connections/fixed-package-budget.json
new file mode 100644
index 0000000..2ae8671
--- /dev/null
+++ b/prototypes/connections/fixed-package-budget.json
@@ -0,0 +1,10 @@
+{
+ "profile": "linux-aarch64-gcc14-fixed-document-package",
+ "max_archive_bytes": {
+ "cli": 16384,
+ "cli_http": 34816,
+ "cli_tui": 35840,
+ "cli_http_tui": 54272
+ },
+ "scope": "Deterministic gzip archive containing selected stripped AArch64 binaries, manifest and usage text. The combined CLI+HTTP+TUI ceiling was reviewed upward by 1 KiB for the bounded document browser; the CLI-only ceiling is unchanged. These are regression ceilings for the current document app and toolchain; they exclude host libc, terminal emulator, kernel buffers and stored documents. Optional hosts are charged to their selected package, not the CLI-only package."
+}
diff --git a/prototypes/connections/flow.c b/prototypes/connections/flow.c
new file mode 100644
index 0000000..1070c70
--- /dev/null
+++ b/prototypes/connections/flow.c
@@ -0,0 +1,41 @@
+#include "flow.h"
+#include <assert.h>
+
+void pure_transfer_abort(PureTransfer *t) {
+ if (!t->active) return;
+ PureRelease release = t->release;
+ void *owner = t->owner;
+ *t = (PureTransfer){0};
+ if (release) release(owner);
+}
+
+static void advance(PureTransfer *t) {
+ while (t->active && t->part < 2 && t->offset == t->spans[t->part].size) {
+ t->part++;
+ t->offset = 0;
+ }
+ if (t->active && t->part == 2) pure_transfer_abort(t);
+}
+
+void pure_transfer_init(PureTransfer *t, PureSpan header, PureSpan body,
+ void *owner, PureRelease release) {
+ assert(!t->active);
+ assert((!header.size || header.data) && (!body.size || body.data));
+ *t = (PureTransfer){.spans = {header, body}, .owner = owner,
+ .release = release, .active = true};
+ advance(t);
+}
+
+PureSpan pure_transfer_next(const PureTransfer *t, size_t limit) {
+ if (!t->active) return (PureSpan){0};
+ PureSpan span = t->spans[t->part];
+ size_t remaining = span.size - t->offset;
+ return (PureSpan){span.data + t->offset, remaining < limit ? remaining : limit};
+}
+
+bool pure_transfer_consume(PureTransfer *t, size_t bytes) {
+ if (!t->active || bytes > t->spans[t->part].size - t->offset) return false;
+ t->offset += bytes;
+ advance(t);
+ return true;
+}
diff --git a/prototypes/connections/flow.h b/prototypes/connections/flow.h
new file mode 100644
index 0000000..6e27c58
--- /dev/null
+++ b/prototypes/connections/flow.h
@@ -0,0 +1,25 @@
+#ifndef PURE_FLOW_H
+#define PURE_FLOW_H
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef struct { const unsigned char *data; size_t size; } PureSpan;
+typedef void (*PureRelease)(void *owner);
+
+/* A borrowed body stays alive until every byte is consumed or the transfer is
+ * aborted. A successful send() consumes bytes; peer receipt is a separate fact.
+ * Single owner thread; callbacks must not reenter or reuse this transfer. */
+typedef struct {
+ PureSpan spans[2];
+ size_t part, offset;
+ void *owner;
+ PureRelease release;
+ bool active;
+} PureTransfer;
+
+void pure_transfer_init(PureTransfer *, PureSpan header, PureSpan body,
+ void *owner, PureRelease);
+PureSpan pure_transfer_next(const PureTransfer *, size_t limit);
+bool pure_transfer_consume(PureTransfer *, size_t bytes);
+void pure_transfer_abort(PureTransfer *);
+#endif
diff --git a/prototypes/connections/hybrid-budget.json b/prototypes/connections/hybrid-budget.json
new file mode 100644
index 0000000..e36b9e7
--- /dev/null
+++ b/prototypes/connections/hybrid-budget.json
@@ -0,0 +1,18 @@
+{
+ "profile": "linux-aarch64-gcc14-selected-hybrid-document-storage",
+ "binaries": {
+ "pure-edit": {
+ "max_text_bytes": 43008,
+ "max_data_bytes": 1200,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ },
+ "pure-connections": {
+ "max_text_bytes": 50176,
+ "max_data_bytes": 1300,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ }
+ },
+ "scope": "Opt-in inline/PUREP001 document store on Linux AArch64/GCC 14. The CLI text ceiling is 42 KiB. The HTTP ceiling is 49 KiB after reviewing its 49133-to-49589-byte growth for the authored final-size guard, which checks the locked document version. This is a selected research budget, not the default micro-runtime budget. Direct dependencies only; excludes libc, process RAM, filesystem cache and journal, optional TLS/GTK."
+}
diff --git a/prototypes/connections/hybrid-tui-budget.json b/prototypes/connections/hybrid-tui-budget.json
new file mode 100644
index 0000000..a5d37f2
--- /dev/null
+++ b/prototypes/connections/hybrid-tui-budget.json
@@ -0,0 +1,12 @@
+{
+ "profile": "linux-aarch64-gcc14-hybrid-source-document-terminal-editor",
+ "binaries": {
+ "pure-edit-tui": {
+ "max_text_bytes": 55296,
+ "max_data_bytes": 1152,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ }
+ },
+ "scope": "Selected source-loaded native document terminal editor with the existing 16 KiB hybrid page store. This ceiling reviews the measured 53,642-byte linked text build on Linux AArch64/GCC 14. It excludes libc, process RSS, mapped document pages and filesystem cache; check_tui.py separately gates actual one-MiB and 1,024-document work. The default core, CLI and TUI do not select this store."
+}
diff --git a/prototypes/connections/measure-peak-rss.c b/prototypes/connections/measure-peak-rss.c
new file mode 100644
index 0000000..1fe2e0b
--- /dev/null
+++ b/prototypes/connections/measure-peak-rss.c
@@ -0,0 +1,43 @@
+#ifdef __APPLE__
+#define _DARWIN_C_SOURCE
+#else
+#define _DEFAULT_SOURCE
+#endif
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+/* Test helper: fork from a small native process so the interpreter's pre-exec
+ * RSS cannot become the measured child's peak. Not shipped. */
+int main(int argc, char **argv) {
+ if (argc < 2) return 2;
+ pid_t child = fork();
+ if (child < 0) return 2;
+ if (!child) {
+ int null = open("/dev/null", O_WRONLY);
+ if (null < 0 || dup2(null, STDOUT_FILENO) < 0 ||
+ dup2(null, STDERR_FILENO) < 0) _exit(127);
+ close(null);
+ execvp(argv[1], argv + 1);
+ _exit(127);
+ }
+ struct rusage usage;
+ int status;
+ if (wait4(child, &status, 0, &usage) < 0) return 2;
+ if (!WIFEXITED(status)) return 2;
+ if (usage.ru_maxrss < 0) return 2;
+#ifdef __APPLE__
+ /* XNU reports ru_maxrss in bytes; Linux reports KiB. */
+ long peak_kib = usage.ru_maxrss / 1024 + (usage.ru_maxrss % 1024 != 0);
+ const char *raw_unit = "bytes";
+#else
+ long peak_kib = usage.ru_maxrss;
+ const char *raw_unit = "KiB";
+#endif
+ printf("{\"exit_code\":%d,\"max_rss_kib\":%ld,"
+ "\"raw_max_rss\":%ld,\"raw_unit\":\"%s\"}\n",
+ WEXITSTATUS(status), peak_kib, usage.ru_maxrss, raw_unit);
+ return 0;
+}
diff --git a/prototypes/connections/measure_tui_latency.py b/prototypes/connections/measure_tui_latency.py
new file mode 100644
index 0000000..569284b
--- /dev/null
+++ b/prototypes/connections/measure_tui_latency.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+"""Measure one visible PTY redraw per edit in the real fixed document app."""
+import argparse
+import fcntl
+import hashlib
+import json
+import os
+from pathlib import Path
+import platform
+import pty
+import select
+import statistics
+import struct
+import subprocess
+import tempfile
+import termios
+import time
+
+HERE = Path(__file__).resolve().parent
+WORKLOADS = {
+ '256-byte-ascii': b'Q' * 256,
+ 'one-mib-ascii': b'Q' * 1_048_576,
+ 'one-mib-utf8': '안녕'.encode() * 174_762,
+}
+
+
+def frame(fd, process):
+ data = bytearray()
+ deadline = time.monotonic() + 15
+ while time.monotonic() < deadline:
+ if select.select([fd], [], [], 0.5)[0]:
+ data.extend(os.read(fd, 65536))
+ if b'\x1b[?25h' in data:
+ return bytes(data)
+ if process.poll() is not None:
+ break
+ raise RuntimeError(f'editor did not finish a frame: exit={process.poll()}, output={data[-300:]!r}')
+
+
+def measure(tui, cli, store, root, name, body):
+ insert = root / f'{name}.insert'
+ insert.write_bytes(body)
+ subprocess.run([cli, '--store', store, 'edit', name, '0', '0', '0', insert],
+ check=True, capture_output=True, timeout=15)
+ master, slave = pty.openpty()
+ fcntl.ioctl(slave, termios.TIOCSWINSZ, struct.pack('HHHH', 24, 80, 0, 0))
+ process = subprocess.Popen([tui, '--store', store, name], stdin=slave,
+ stdout=slave, stderr=slave,
+ env={**os.environ, 'LANG': 'C.UTF-8'})
+ try:
+ frame(master, process)
+ samples = []
+ for _ in range(10):
+ start = time.perf_counter_ns()
+ os.write(master, b'Z')
+ shown = frame(master, process)
+ samples.append({'nanoseconds': time.perf_counter_ns() - start,
+ 'frame_bytes': len(shown),
+ 'frame_sha256': hashlib.sha256(shown).hexdigest()})
+ os.write(master, b'\x11')
+ frame(master, process)
+ os.write(master, b'\x11')
+ process.wait(timeout=5)
+ if process.returncode:
+ raise RuntimeError(f'editor exit={process.returncode}')
+ return {'document_bytes': len(body), 'samples': samples,
+ 'median_nanoseconds': int(statistics.median(s['nanoseconds'] for s in samples))}
+ finally:
+ if process.poll() is None:
+ process.kill()
+ process.wait(timeout=5)
+ os.close(master)
+ os.close(slave)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--tui', type=Path, required=True)
+ parser.add_argument('--cli', type=Path, default=HERE / 'build/pure-edit-fixed')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ tui, cli = args.tui.resolve(), args.cli.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-tui-latency-') as directory:
+ root = Path(directory)
+ workloads = {name: measure(tui, cli, root / 'store', root, name, body)
+ for name, body in WORKLOADS.items()}
+ result = {'platform': platform.platform(), 'terminal': 'PTY 24x80, C.UTF-8',
+ 'tui_sha256': hashlib.sha256(tui.read_bytes()).hexdigest(),
+ 'cli_sha256': hashlib.sha256(cli.read_bytes()).hexdigest(),
+ 'workloads': workloads}
+ text = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ args.output.write_text(text)
+ print(text, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/memory-budget.json b/prototypes/connections/memory-budget.json
new file mode 100644
index 0000000..320e011
--- /dev/null
+++ b/prototypes/connections/memory-budget.json
@@ -0,0 +1,7 @@
+{
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "max_small_edit_rss_kib": 4096,
+ "max_one_mib_edit_rss_kib": 4096,
+ "max_one_mib_show_rss_kib": 4096,
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee."
+}
diff --git a/prototypes/connections/mirror.c b/prototypes/connections/mirror.c
new file mode 100644
index 0000000..34ff1bf
--- /dev/null
+++ b/prototypes/connections/mirror.c
@@ -0,0 +1,145 @@
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include "storage-plan.h"
+
+enum { MAX_TARGETS = 8 };
+typedef struct {
+ PureRuntime runtime;
+ PureWork work[1];
+ PureTicket ticket;
+ PureOutcome outcome;
+} Target;
+
+static const char *result_name(PureResult result) {
+ static const char *const names[] = {
+ "ok", "not_found", "conflict", "busy", "budget", "limit",
+ "store_error", "durability_unknown", "invalid", "denied",
+ "closed", "cancelled", "allocation"
+ };
+ return (unsigned)result < sizeof(names) / sizeof(names[0]) ? names[result] : "unknown";
+}
+
+static bool number(const char *text, uint64_t limit, uint64_t *out) {
+ uint64_t value = 0;
+ if (!*text) return false;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > limit || value > (limit - digit) / 10) return false;
+ value = value * 10 + digit;
+ }
+ *out = value;
+ return true;
+}
+
+int main(int argc, char **argv) {
+ int at = 1;
+ size_t target_budget = PURE_OBJECT_LIMIT;
+ uint64_t parsed;
+ if (argc > 2 && !strcmp(argv[1], "--target-budget")) {
+ if (!number(argv[2], SIZE_MAX, &parsed)) return 2;
+ target_budget = (size_t)parsed;
+ at += 2;
+ }
+ if (argc - at < 5 || (argc - at - 2) % 3 ||
+ (argc - at - 2) / 3 > MAX_TARGETS) {
+ fputs("usage: pure-mirror [--target-budget BYTES] SOURCE_STORE SOURCE_KEY TARGET_STORE TARGET_KEY EXPECTED_REVISION [TARGET_STORE TARGET_KEY EXPECTED_REVISION ...]\n", stderr);
+ return 2;
+ }
+ size_t count = (size_t)(argc - at - 2) / 3;
+ int64_t expected[MAX_TARGETS];
+ for (size_t i = 0; i < count; ++i) {
+ if (!number(argv[at + 4 + i * 3], INT64_MAX, &parsed)) return 2;
+ expected[i] = (int64_t)parsed;
+ }
+ if (pure_store_init(argv[at]) != PURE_OK) return 2;
+ PureRuntime source;
+ PureWork source_work[1];
+ if (!pure_runtime_init(&source, source_work, 1, &pure_embedded_program,
+ pure_store_host(argv[at]), PURE_OBJECT_LIMIT)) return 2;
+ PureTicket read;
+ PureResult status = pure_runtime_accept(&source, PURE_INPUT_READ, argv[at + 1], 0, 0, &read);
+ if (status != PURE_OK) {
+ printf("{\"source_status\":\"%s\"}\n", result_name(status));
+ return 2;
+ }
+ PureOutcome snapshot;
+ if (!pure_runtime_step(&source) || !pure_runtime_result(read, &snapshot)) {
+ pure_runtime_release(read);
+ return 2;
+ }
+ if (snapshot.status != PURE_OK) {
+ printf("{\"source_status\":\"%s\"}\n", result_name(snapshot.status));
+ pure_runtime_release(read);
+ return 2;
+ }
+ Target targets[MAX_TARGETS] = {0};
+ size_t forwarded = 0;
+ for (size_t i = 0; i < count; ++i) {
+ const char *store = argv[at + 2 + i * 3], *key = argv[at + 3 + i * 3];
+ PureHost host = pure_store_host(store);
+ host.allocate = NULL; /* Forwarded ingress uses the source mapping. */
+ if (pure_store_init(store) != PURE_OK ||
+ !pure_runtime_init(&targets[i].runtime, targets[i].work, 1,
+ &pure_embedded_program, host,
+ target_budget)) status = PURE_STORE_ERROR;
+ else status = pure_runtime_forward(read, &targets[i].runtime, key,
+ expected[i], &targets[i].ticket);
+ if (status != PURE_OK) {
+ for (size_t j = 0; j < forwarded; ++j) {
+ pure_runtime_cancel(targets[j].ticket);
+ pure_runtime_release(targets[j].ticket);
+ }
+ pure_runtime_release(read);
+ printf("{\"admission_status\":\"%s\",\"target_index\":%zu}\n",
+ result_name(status), i);
+ return 2;
+ }
+ ++forwarded;
+ }
+ /* Each queued target pins the mapped source snapshot independently. */
+ pure_runtime_release(read);
+ if (snapshot.body.size && source.retained != snapshot.body.size) {
+ for (size_t i = 0; i < count; ++i) {
+ pure_runtime_cancel(targets[i].ticket);
+ pure_runtime_release(targets[i].ticket);
+ }
+ return 2;
+ }
+ int exit_status = 0;
+ for (size_t i = 0; i < count; ++i) {
+ if (!pure_runtime_step(&targets[i].runtime) ||
+ !pure_runtime_result(targets[i].ticket, &targets[i].outcome)) {
+ for (size_t j = i; j < count; ++j) {
+ pure_runtime_cancel(targets[j].ticket);
+ pure_runtime_release(targets[j].ticket);
+ }
+ return 2;
+ }
+ if (targets[i].outcome.status == PURE_CONFLICT && !exit_status) exit_status = 3;
+ else if (targets[i].outcome.status != PURE_OK &&
+ targets[i].outcome.status != PURE_CONFLICT) exit_status = 2;
+ pure_runtime_release(targets[i].ticket);
+ if (snapshot.body.size && i + 1 < count &&
+ source.retained != snapshot.body.size) {
+ for (size_t j = i + 1; j < count; ++j) {
+ pure_runtime_cancel(targets[j].ticket);
+ pure_runtime_release(targets[j].ticket);
+ }
+ return 2;
+ }
+ }
+ if (source.active || source.retained) return 2;
+ printf("{\"source_revision\":\"%" PRId64 "\",\"bytes\":%zu,\"targets\":[",
+ snapshot.revision, snapshot.body.size);
+ for (size_t i = 0; i < count; ++i)
+ printf("%s{\"index\":%zu,\"status\":\"%s\",\"revision\":\"%" PRId64 "\"}",
+ i ? "," : "", i, result_name(targets[i].outcome.status),
+ targets[i].outcome.revision);
+ puts("]}");
+ return fflush(stdout) ? 2 : exit_status;
+}
diff --git a/prototypes/connections/package_native.py b/prototypes/connections/package_native.py
new file mode 100644
index 0000000..7ee9c4f
--- /dev/null
+++ b/prototypes/connections/package_native.py
@@ -0,0 +1,361 @@
+#!/usr/bin/env python3
+"""Bundle the selected Linux document app without folding hosts into the core."""
+import argparse
+import gzip
+import hashlib
+import io
+import json
+from pathlib import Path
+import platform
+import re
+import subprocess
+import tarfile
+import tempfile
+
+HERE = Path(__file__).resolve().parent
+NEEDED = re.compile(r'\(NEEDED\).*Shared library: \[([^]]+)\]')
+ROOT_NAME = 'pure-document'
+PAGED_STORAGE = """# Selected page storage format
+
+This preview uses the PUREP001 16 KiB-page store. It cannot open PUREB001
+flat-store objects. Use a new --store directory; this is a research format,
+not a migration or a default storage backend. Small objects currently pay a
+full-page write cost. See docs/research/033-paged-document-storage.md in the
+source repository for measured boundaries and limitations.
+"""
+HYBRID_STORAGE = """# Selected inline/page storage experiment
+
+Objects up to 16 KiB use the existing PUREB001 file format. Larger objects
+use PUREP001 page roots and append-only data generations. The current flat
+binary cannot read PUREP001 objects, so use a new --store directory for this
+preview. This is a selected research build, not the default backend or a
+bidirectional migration path. It requires a Linux host with 16 KiB OS pages.
+See docs/research/034-hybrid-document-storage.md in the source repository.
+"""
+
+RUN = """# Pure document preview — Linux native build
+
+This archive includes the CLI and editable editor.pure program. HTTP, TLS peer,
+and GTK hosts are included only when listed in manifest.json. Shared system libraries are not bundled;
+manifest.json records every binary's direct dependencies.
+
+From this directory, try a local edit:
+
+ printf 'hello Pure\\n' > /tmp/pure-insert.txt
+ bin/pure-edit --program share/editor.pure --store /tmp/pure-preview-store \\
+ edit note 0 0 0 /tmp/pure-insert.txt
+ bin/pure-edit --program share/editor.pure --store /tmp/pure-preview-store show note
+
+When selected, the same program and store can be opened with the GTK window:
+
+ bin/pure-edit-window --program share/editor.pure \\
+ --store /tmp/pure-preview-store note
+
+When selected, the source-loaded terminal editor uses the same program and
+store without GTK. Edit share/editor.pure, then start a new TUI session to
+load the changed definition:
+
+ bin/pure-edit-tui --program share/editor.pure \\
+ --store /tmp/pure-preview-store note
+
+When selected, the TLS peer needs your own CA and server/client certificates. The server
+certificate needs a DNS SAN matching SERVER_DNS; the client certificate needs
+a DNS SAN matching CLIENT_DNS. This example binds only to loopback:
+
+ bin/pure-document-peer serve 127.0.0.1 9443 share/editor.pure \\
+ /tmp/pure-preview-store CA.pem SERVER.pem SERVER.key CLIENT_DNS
+ bin/pure-document-peer call 127.0.0.1 9443 SERVER_DNS share/editor.pure \\
+ CA.pem CLIENT.pem CLIENT.key show note
+
+If manifest.json lists pure-document-server instead, run:
+
+ bin/pure-document-server serve 127.0.0.1 9443 share/editor.pure \\
+ /tmp/pure-preview-store CA.pem SERVER.pem SERVER.key CLIENT_DNS
+
+That selection omits the native `call` command; connect with an authenticated
+external client using the pure-doc/1 binary protocol.
+
+When selected, the HTTP host is a plaintext compatibility adapter; bind it only to loopback.
+This preview was checked on Linux AArch64. It is not a static or macOS package.
+"""
+RUN_FIXED = """# Pure fixed document runner — Linux AArch64
+
+This artifact runs one build-time prepared editor.pure definition. It has no
+source parser, compiler, GTK or TLS host. Editing a .pure file does not
+change this binary; rebuild it with `make fixed-editor` in the source tree.
+
+ bin/pure-edit-fixed --store STORE edit KEY 0 0 0 INSERT_FILE
+ bin/pure-edit-fixed --store STORE show KEY
+
+When manifest.json lists pure-connections-fixed, it serves the same definition
+and store through a loopback HTTP compatibility boundary:
+
+ bin/pure-connections-fixed --store STORE --port 8767
+
+When manifest.json lists pure-edit-tui-fixed, it opens a native terminal
+editor for the same stored document. Ctrl+S saves, Ctrl+O enters another key,
+Ctrl+L browses stored keys (type a prefix to jump), Ctrl+R reloads, and
+Ctrl+Q quits:
+
+ bin/pure-edit-tui-fixed --store STORE note
+
+The external storage files use the default PUREB001 format. The ELF binary
+needs the host's libc and is not a static or macOS package.
+"""
+
+
+def dependencies(path):
+ header = subprocess.check_output(['readelf', '-h', str(path)], text=True)
+ if not re.search(r'Machine:\s+AArch64\s*$', header, re.MULTILINE):
+ raise ValueError(f'{path} is not an AArch64 ELF')
+ output = subprocess.check_output(['readelf', '-d', str(path)], text=True)
+ return sorted(NEEDED.findall(output))
+
+
+def reviewed_budget(build, name, selected=()):
+ command = ['python3', str(HERE / 'check_profile.py'), '--build', str(build),
+ '--budget', str(HERE / name)]
+ for binary in selected:
+ command.extend(['--only', binary])
+ result = subprocess.run(command, capture_output=True, text=True)
+ if result.returncode:
+ raise ValueError(f'{name} failed: {result.stdout or result.stderr}')
+ checked = json.loads(result.stdout)
+ return {'profile': checked['profile'], 'budget_sha256': checked['budget_sha256'],
+ 'checked_binaries': sorted(checked['binaries'])}
+
+
+def reviewed_memory(build, fixed=False):
+ result = subprocess.run(['python3', str(HERE / 'check_micro_memory.py'),
+ '--build', str(build), *(['--fixed'] if fixed else [])],
+ capture_output=True, text=True)
+ if result.returncode:
+ raise ValueError(f'memory-budget.json failed: {result.stdout or result.stderr}')
+ checked = json.loads(result.stdout)
+ return {'profile': checked['profile'], 'budget_sha256': checked['budget_sha256']}
+
+
+def reviewed_tui_memory(build, source=False):
+ result = subprocess.run(['python3', str(HERE / 'check_tui.py'), '--build', str(build),
+ *(['--source'] if source else [])],
+ capture_output=True, text=True)
+ if result.returncode:
+ raise ValueError(f'terminal editor check failed: {result.stdout or result.stderr}')
+ checked = json.loads(result.stdout)
+ return {'profile': checked['profile'],
+ 'one_mib_peak_rss_limit_kib': checked['one_mib_peak_rss_limit_kib'],
+ 'binary_sha256': checked['binary_sha256']}
+
+
+def add_bytes(archive, name, content, mode):
+ info = tarfile.TarInfo(ROOT_NAME + '/' + name)
+ info.size = len(content)
+ info.mode = mode
+ info.mtime = 0
+ info.uid = info.gid = 0
+ info.uname = info.gname = ''
+ archive.addfile(info, io.BytesIO(content))
+
+
+def without_debug(source, compact=False):
+ # The release build retains symbols for local debugging; the runnable
+ # fixed package needs neither DWARF nor unused symbols. Never mutate the
+ # build used by size checks or source/authoring package symbols.
+ with tempfile.TemporaryDirectory(prefix='pure-package-strip-') as directory:
+ destination = Path(directory) / source.name
+ destination.write_bytes(source.read_bytes())
+ subprocess.run(['strip', '--strip-unneeded' if compact else '--strip-debug',
+ str(destination)], check=True)
+ if dependencies(destination) != dependencies(source):
+ raise ValueError(f'{source}: stripping changed direct dependencies')
+ return destination.read_bytes()
+
+
+def verify_storage(binary, mode):
+ with tempfile.TemporaryDirectory(prefix='pure-package-store-probe-') as directory:
+ root = Path(directory)
+ payload = root / 'insert'
+ payload.write_bytes(b'X')
+ result = subprocess.run([str(binary), '--program', str(HERE / 'examples/editor.pure'),
+ '--store', str(root / 'store'), 'edit', 'probe', '0', '0', '0',
+ str(payload)], capture_output=True, timeout=15)
+ expected = b'PUREB001' if mode == 'hybrid' else b'PUREP001'
+ if result.returncode or (root / 'store/obj-probe').read_bytes()[:8] != expected:
+ raise ValueError(f'{binary} is not a working {mode} CLI: {result.stderr[-300:]}')
+ if mode == 'hybrid':
+ payload.write_bytes(b'X' * (16 * 1024 + 1))
+ result = subprocess.run([str(binary), '--program', str(HERE / 'examples/editor.pure'),
+ '--store', str(root / 'store'), 'edit', 'large', '0', '0', '0',
+ str(payload)], capture_output=True, timeout=15)
+ if result.returncode or (root / 'store/obj-large').read_bytes()[:8] != b'PUREP001':
+ raise ValueError(f'{binary} does not select PUREP001 for large objects')
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--build', type=Path, default=HERE / 'build')
+ parser.add_argument('--output', type=Path, required=True)
+ parser.add_argument('--with-http', action='store_true')
+ parser.add_argument('--with-tui', action='store_true')
+ peer = parser.add_mutually_exclusive_group()
+ peer.add_argument('--with-peer', action='store_true',
+ help='include the combined native TLS client/server')
+ peer.add_argument('--with-peer-server', action='store_true',
+ help='include only the authenticated TLS server')
+ parser.add_argument('--with-window', action='store_true')
+ parser.add_argument('--fixed', action='store_true',
+ help='package only the parser-free build-time prepared editor')
+ storage = parser.add_mutually_exclusive_group()
+ storage.add_argument('--paged-storage', action='store_true',
+ help='package the historical PUREP001-only storage backend')
+ storage.add_argument('--hybrid-storage', action='store_true',
+ help='package the selected PUREB001/PUREP001 storage experiment')
+ args = parser.parse_args()
+ if platform.system() != 'Linux' or platform.machine() != 'aarch64':
+ parser.error('this reviewed package profile is Linux AArch64 only')
+ if args.output.exists():
+ parser.error('output already exists')
+ if args.fixed and (args.with_peer or args.with_peer_server or args.with_window or
+ args.paged_storage or args.hybrid_storage):
+ parser.error('--fixed selects only the flat-store CLI and optional HTTP/TUI hosts')
+ if args.with_tui and args.paged_storage:
+ parser.error('--with-tui supports the default or selected hybrid store')
+ if (args.with_peer or args.with_peer_server) and (args.paged_storage or args.hybrid_storage):
+ parser.error('the document TLS peer currently uses the default flat store')
+ if args.fixed:
+ built = subprocess.run(['make', '-C', str(HERE), f'BUILD={args.build.resolve()}',
+ 'FIXED_PROGRAM=examples/editor.pure', 'fixed-editor',
+ *(['fixed-server'] if args.with_http else []),
+ *(['fixed-tui'] if args.with_tui else [])],
+ capture_output=True, text=True)
+ if built.returncode:
+ parser.error(f'could not prepare the fixed editor: {built.stderr[-500:]}')
+ elif args.with_tui:
+ built = subprocess.run(['make', '-C', str(HERE), f'BUILD={args.build.resolve()}',
+ *(['STORE=store-paged.c'] if args.hybrid_storage else []),
+ 'editor', 'source-tui'], capture_output=True, text=True)
+ if built.returncode:
+ parser.error(f'could not prepare the source editor: {built.stderr[-500:]}')
+ if args.with_peer_server:
+ built = subprocess.run(['make', '-C', str(HERE), f'BUILD={args.build.resolve()}',
+ 'editor', 'document-server'], capture_output=True, text=True)
+ if built.returncode:
+ parser.error(f'could not prepare the server-only peer: {built.stderr[-500:]}')
+ if args.paged_storage or args.hybrid_storage:
+ verify_storage(args.build / 'pure-edit', 'hybrid' if args.hybrid_storage else 'paged')
+ helper = args.build.resolve() / 'measure-peak-rss'
+ built = subprocess.run(['make', '-C', str(HERE), f'BUILD={args.build.resolve()}',
+ str(helper)], capture_output=True, text=True)
+ if built.returncode:
+ parser.error(f'could not prepare the RSS helper: {built.stderr[-500:]}')
+ binaries = ['pure-edit-fixed' if args.fixed else 'pure-edit']
+ if args.with_http:
+ binaries.append('pure-connections-fixed' if args.fixed else 'pure-connections')
+ if args.with_tui:
+ binaries.append('pure-edit-tui-fixed' if args.fixed else 'pure-edit-tui')
+ if args.with_peer:
+ binaries.append('pure-document-peer')
+ if args.with_peer_server:
+ binaries.append('pure-document-server')
+ if args.with_window:
+ binaries.append('pure-edit-window')
+ entries = {}
+ manifest_files = {}
+ for binary in binaries:
+ source = args.build / binary
+ content = without_debug(source, args.fixed)
+ if content[:4] != b'\x7fELF':
+ parser.error(f'{source} is not an ELF binary')
+ name = 'bin/' + binary
+ entries[name] = (content, 0o755)
+ manifest_files[name] = {'sha256': hashlib.sha256(content).hexdigest(),
+ 'bytes': len(content), 'needed': dependencies(source)}
+ program = (HERE / 'examples/editor.pure').read_bytes()
+ if not args.fixed:
+ entries['share/editor.pure'] = (program, 0o644)
+ manifest_files['share/editor.pure'] = {'sha256': hashlib.sha256(program).hexdigest(),
+ 'bytes': len(program)}
+ entries['RUN.md'] = ((RUN_FIXED if args.fixed else RUN).encode(), 0o644)
+ manifest_files['RUN.md'] = {'sha256': hashlib.sha256(entries['RUN.md'][0]).hexdigest(),
+ 'bytes': len(entries['RUN.md'][0])}
+ if args.paged_storage or args.hybrid_storage:
+ entries['STORAGE.md'] = ((HYBRID_STORAGE if args.hybrid_storage else PAGED_STORAGE).encode(), 0o644)
+ manifest_files['STORAGE.md'] = {'sha256': hashlib.sha256(entries['STORAGE.md'][0]).hexdigest(),
+ 'bytes': len(entries['STORAGE.md'][0])}
+ budgets = [reviewed_budget(args.build,
+ 'fixed-budget.json' if args.fixed else
+ 'hybrid-budget.json' if args.hybrid_storage else
+ 'paged-budget.json' if args.paged_storage else 'profile-budget.json',
+ ['pure-edit-fixed'] +
+ (['pure-connections-fixed'] if args.with_http else []) if args.fixed else
+ ['pure-edit'] + (['pure-connections'] if args.with_http else []))]
+ if args.with_peer:
+ budgets.append(reviewed_budget(args.build, 'peer-budget.json'))
+ if args.with_peer_server:
+ budgets.append(reviewed_budget(args.build, 'peer-server-budget.json'))
+ if args.with_tui:
+ budgets.append(reviewed_budget(args.build,
+ 'tui-budget.json' if args.fixed else
+ 'hybrid-tui-budget.json' if args.hybrid_storage else
+ 'source-tui-budget.json'))
+ if args.with_window:
+ budgets.append(reviewed_budget(args.build, 'window-budget.json'))
+ manifest = {'format': 'pure-document-preview-1', 'platform': 'linux-aarch64',
+ 'selected_hosts': binaries, 'shared_libraries_bundled': False,
+ 'reviewed_budgets': budgets, 'reviewed_memory': reviewed_memory(args.build, args.fixed),
+ 'files': manifest_files}
+ if args.fixed:
+ manifest['program_mode'] = 'build-time-prepared'
+ manifest['source_sha256'] = hashlib.sha256(program).hexdigest()
+ if args.with_tui:
+ manifest['reviewed_tui_memory'] = reviewed_tui_memory(args.build, not args.fixed)
+ if args.with_window:
+ manifest['features'] = ['native-document-key-switch']
+ if args.paged_storage:
+ manifest['storage_profile'] = 'PUREP001-16k-page-research'
+ if args.hybrid_storage:
+ manifest['storage_profile'] = 'PUREB001+PUREP001-hybrid-16k-research'
+ maximum = None
+ package_profile = None
+ if args.fixed:
+ budget_path = HERE / 'fixed-package-budget.json'
+ package_budget = json.loads(budget_path.read_text())
+ package_profile = 'cli' + ('_http' if args.with_http else '') + ('_tui' if args.with_tui else '')
+ maximum = package_budget['max_archive_bytes'][package_profile]
+ manifest['reviewed_package_budget'] = {
+ 'profile': package_budget['profile'], 'selection': package_profile,
+ 'max_archive_bytes': maximum,
+ 'budget_sha256': hashlib.sha256(budget_path.read_bytes()).hexdigest()}
+ elif (args.with_peer or args.with_peer_server) and not (
+ args.with_http or args.with_tui or args.with_window or
+ args.paged_storage or args.hybrid_storage):
+ budget_path = HERE / 'peer-package-budget.json'
+ package_budget = json.loads(budget_path.read_text())
+ package_profile = 'server_only' if args.with_peer_server else 'combined'
+ maximum = package_budget['max_archive_bytes'][package_profile]
+ manifest['reviewed_package_budget'] = {
+ 'profile': package_budget['profile'], 'selection': package_profile,
+ 'max_archive_bytes': maximum,
+ 'budget_sha256': hashlib.sha256(budget_path.read_bytes()).hexdigest()}
+ entries['manifest.json'] = ((json.dumps(manifest, indent=2, sort_keys=True) + '\n').encode(), 0o644)
+ stream = io.BytesIO()
+ with gzip.GzipFile(filename='', mode='wb', fileobj=stream, mtime=0) as compressed:
+ with tarfile.open(fileobj=compressed, mode='w') as archive:
+ for name in sorted(entries):
+ content, mode = entries[name]
+ add_bytes(archive, name, content, mode)
+ packed = stream.getvalue()
+ if maximum is not None and len(packed) > maximum:
+ parser.error(f'{package_profile} archive grew to {len(packed)} bytes '
+ f'(reviewed maximum {maximum}); no package was published')
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('xb') as output:
+ output.write(packed)
+ print(json.dumps({'archive': str(args.output.resolve()),
+ 'sha256': hashlib.sha256(packed).hexdigest(),
+ 'bytes': len(packed),
+ 'selected_hosts': binaries}, sort_keys=True))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/package_source.py b/prototypes/connections/package_source.py
new file mode 100644
index 0000000..4a2487c
--- /dev/null
+++ b/prototypes/connections/package_source.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+"""Make a deterministic, buildable source snapshot without result/build trees."""
+import argparse
+import gzip
+import hashlib
+import io
+import json
+from pathlib import Path
+import tarfile
+
+ROOT = Path(__file__).resolve().parents[2]
+PREFIX = 'pure-source-preview'
+SOURCE_ROOTS = ('prototypes/connections', 'prototypes/workbench', 'prototypes/common')
+SKIP_DIRS = {'build', 'results', '__pycache__', 'node_modules', '.git', '.playwright-cli'}
+SUFFIXES = {'.c', '.h', '.py', '.mjs', '.js', '.zig', '.json', '.pure',
+ '.html', '.css', '.svg', '.wasm', '.md', '.txt'}
+
+
+def files():
+ selected = {}
+ for relative_root in SOURCE_ROOTS:
+ for path in (ROOT / relative_root).rglob('*'):
+ relative = path.relative_to(ROOT)
+ if any(part in SKIP_DIRS for part in relative.parts) or path.is_symlink() or not path.is_file():
+ continue
+ if path.name != 'Makefile' and path.suffix not in SUFFIXES:
+ continue
+ selected[relative.as_posix()] = path.read_bytes()
+ return selected
+
+
+def add(archive, name, content):
+ info = tarfile.TarInfo(PREFIX + '/' + name)
+ info.size = len(content)
+ info.mode = 0o644
+ info.mtime = info.uid = info.gid = 0
+ info.uname = info.gname = ''
+ archive.addfile(info, io.BytesIO(content))
+
+
+def make_archive(output):
+ selected = files()
+ selected['RUN.md'] = selected.pop('prototypes/connections/SOURCE_PREVIEW.md')
+ manifest = {'format': 'pure-source-preview-1', 'files': {
+ name: {'bytes': len(content), 'sha256': hashlib.sha256(content).hexdigest()}
+ for name, content in sorted(selected.items())}}
+ selected['manifest.json'] = (json.dumps(manifest, indent=2, sort_keys=True) + '\n').encode()
+ output.parent.mkdir(parents=True, exist_ok=True)
+ with output.open('xb') as stream:
+ with gzip.GzipFile(fileobj=stream, mode='wb', filename='', mtime=0, compresslevel=9) as compressed:
+ with tarfile.open(fileobj=compressed, mode='w', format=tarfile.USTAR_FORMAT) as archive:
+ for name, content in sorted(selected.items()):
+ add(archive, name, content)
+ return {'archive': str(output.resolve()), 'bytes': output.stat().st_size,
+ 'sha256': hashlib.sha256(output.read_bytes()).hexdigest(),
+ 'source_files': len(manifest['files'])}
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--output', type=Path, required=True)
+ args = parser.parse_args()
+ print(json.dumps(make_archive(args.output), sort_keys=True))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/paged-budget.json b/prototypes/connections/paged-budget.json
new file mode 100644
index 0000000..1d578cd
--- /dev/null
+++ b/prototypes/connections/paged-budget.json
@@ -0,0 +1,18 @@
+{
+ "profile": "linux-aarch64-gcc14-selected-paged-document-storage",
+ "binaries": {
+ "pure-edit": {
+ "max_text_bytes": 40960,
+ "max_data_bytes": 1200,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ },
+ "pure-connections": {
+ "max_text_bytes": 49152,
+ "max_data_bytes": 1300,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ }
+ },
+ "scope": "Selected 16 KiB-page document storage backend on Linux AArch64/GCC 14. Same linked-code and direct-dependency ceilings as the flat backend; excludes libc, process RAM, filesystem cache and journal, and optional TLS/GTK. Any failure requires review, not automatic relaxation."
+}
diff --git a/prototypes/connections/peer-budget.json b/prototypes/connections/peer-budget.json
new file mode 100644
index 0000000..b0f7739
--- /dev/null
+++ b/prototypes/connections/peer-budget.json
@@ -0,0 +1,12 @@
+{
+ "profile": "linux-aarch64-gcc14-selected-document-peer",
+ "binaries": {
+ "pure-document-peer": {
+ "max_text_bytes": 53248,
+ "max_data_bytes": 1600,
+ "max_bss_bytes": 64,
+ "needed": ["libssl.so.3", "libcrypto.so.3", "libc.so.6"]
+ }
+ },
+ "scope": "Review threshold for the explicitly selected authenticated document host on Linux AArch64/GCC 14. Includes linked application code but excludes the shared OpenSSL/libc implementations, process heap, stack, mappings and kernel buffers. Check measured whole-process RSS separately."
+}
diff --git a/prototypes/connections/peer-package-budget.json b/prototypes/connections/peer-package-budget.json
new file mode 100644
index 0000000..3403302
--- /dev/null
+++ b/prototypes/connections/peer-package-budget.json
@@ -0,0 +1,8 @@
+{
+ "profile": "linux-aarch64-gcc14-cli-with-selected-document-peer",
+ "max_archive_bytes": {
+ "server_only": 51200,
+ "combined": 53248
+ },
+ "scope": "Compressed CLI plus one TLS peer, source definition and manifest on Linux AArch64. These are reviewed archive ceilings, not process memory or bundled OpenSSL size. Additional HTTP, TUI, GUI or research storage selections have separate costs."
+}
diff --git a/prototypes/connections/peer-server-budget.json b/prototypes/connections/peer-server-budget.json
new file mode 100644
index 0000000..cbb3cc9
--- /dev/null
+++ b/prototypes/connections/peer-server-budget.json
@@ -0,0 +1,12 @@
+{
+ "profile": "linux-aarch64-gcc14-selected-document-server",
+ "binaries": {
+ "pure-document-server": {
+ "max_text_bytes": 45056,
+ "max_data_bytes": 1408,
+ "max_bss_bytes": 64,
+ "needed": ["libssl.so.3", "libcrypto.so.3", "libc.so.6"]
+ }
+ },
+ "scope": "Reviewed server-only TLS peer ceiling on Linux AArch64/GCC 14. Excludes linked native client code and shared OpenSSL/libc implementations; process RSS is measured separately."
+}
diff --git a/prototypes/connections/profile-budget.json b/prototypes/connections/profile-budget.json
new file mode 100644
index 0000000..602f837
--- /dev/null
+++ b/prototypes/connections/profile-budget.json
@@ -0,0 +1,18 @@
+{
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "binaries": {
+ "pure-edit": {
+ "max_text_bytes": 40960,
+ "max_data_bytes": 1200,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ },
+ "pure-connections": {
+ "max_text_bytes": 49152,
+ "max_data_bytes": 1300,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ }
+ },
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation."
+}
diff --git a/prototypes/connections/program.c b/prototypes/connections/program.c
new file mode 100644
index 0000000..780d11a
--- /dev/null
+++ b/prototypes/connections/program.c
@@ -0,0 +1,374 @@
+#include "program.h"
+#include "store.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+enum { NAME = 256, NUMBER, SYMBOLS = 32, LAYOUTS = 4, FIELDS = 16 };
+typedef enum { BYTE_VALUE, RESULT_VALUE, LAYOUT_VALUE, INDEX_VALUE } ValueKind;
+typedef struct {
+ char name[32];
+ ValueKind kind;
+ PureRegion region;
+ size_t step, layout;
+ PureIndex index;
+} Symbol;
+typedef struct {
+ char name[32];
+ size_t offset, length;
+ bool number, tail;
+} Field;
+typedef struct {
+ char name[32];
+ Field fields[FIELDS];
+ size_t count, prefix;
+ bool tail;
+} Layout;
+typedef struct {
+ const char *source;
+ size_t length, at, line, token_line;
+ int token;
+ char name[32];
+ size_t number;
+ char *error;
+ size_t error_size;
+ bool failed, put, effect;
+ Symbol symbols[SYMBOLS];
+ size_t count, layout_count;
+ Layout layouts[LAYOUTS];
+ PureProgram program;
+} Parser;
+
+static bool reject(Parser *p, const char *message) {
+ if (!p->failed && p->error_size) snprintf(p->error, p->error_size, "line %zu: %s", p->token_line, message);
+ p->failed = true;
+ return false;
+}
+
+static bool letter(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
+}
+
+static bool next(Parser *p) {
+ while (p->at < p->length) {
+ char c = p->source[p->at];
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ if (c == '\n') ++p->line;
+ ++p->at;
+ } else if (c == '/' && p->at + 1 < p->length && p->source[p->at + 1] == '/') {
+ while (p->at < p->length && p->source[p->at] != '\n') ++p->at;
+ } else break;
+ }
+ p->token_line = p->line;
+ p->name[0] = 0;
+ p->token = 0;
+ if (p->at == p->length) return true;
+ char c = p->source[p->at++];
+ if (letter(c)) {
+ size_t start = p->at - 1;
+ while (p->at < p->length && (letter(p->source[p->at]) ||
+ (p->source[p->at] >= '0' && p->source[p->at] <= '9'))) ++p->at;
+ size_t size = p->at - start;
+ if (size >= sizeof(p->name)) return reject(p, "name exceeds 31 bytes");
+ memcpy(p->name, p->source + start, size);
+ p->name[size] = 0;
+ p->token = NAME;
+ } else if (c >= '0' && c <= '9') {
+ size_t value = (size_t)(c - '0');
+ while (p->at < p->length && p->source[p->at] >= '0' && p->source[p->at] <= '9') {
+ unsigned digit = (unsigned)(p->source[p->at++] - '0');
+ if (value > (SIZE_MAX - digit) / 10) return reject(p, "integer overflow");
+ value = value * 10 + digit;
+ }
+ p->number = value;
+ p->token = NUMBER;
+ } else if (c && strchr("{}().,=;:[]", c)) p->token = (unsigned char)c;
+ else return reject(p, "unexpected character");
+ return true;
+}
+
+static bool is_word(Parser *p, const char *word) {
+ return p->token == NAME && !strcmp(p->name, word);
+}
+
+static bool word(Parser *p, const char *expected) {
+ return is_word(p, expected) ? next(p) : reject(p, expected);
+}
+
+static bool token(Parser *p, int expected) {
+ return p->token == expected ? next(p) : reject(p, "unexpected token");
+}
+
+static Symbol *find(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->count; ++i)
+ if (!strcmp(name, p->symbols[i].name)) return &p->symbols[i];
+ return NULL;
+}
+
+static bool field(Parser *p, const char *object, const char *name) {
+ return word(p, object) && token(p, '.') && word(p, name);
+}
+
+static bool require_bytes(Parser *p, const Symbol *value) {
+ return value->kind == BYTE_VALUE || reject(p, "expected bytes; select a byte field");
+}
+
+static void require_length(Parser *p, size_t required) {
+ size_t *minimum = p->put ? &p->program.input_required : &p->program.read_required;
+ if (required > *minimum) *minimum = required;
+}
+
+static Layout *find_layout(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->layout_count; ++i)
+ if (!strcmp(name, p->layouts[i].name)) return &p->layouts[i];
+ return NULL;
+}
+
+static bool layout_definition(Parser *p) {
+ if (p->layout_count == LAYOUTS) return reject(p, "program exceeds 4 layouts");
+ if (!next(p)) return false;
+ if (p->token != NAME || find_layout(p, p->name)) return reject(p, "expected a unique layout name");
+ Layout *layout = &p->layouts[p->layout_count];
+ strcpy(layout->name, p->name);
+ if (!next(p) || !token(p, '{')) return false;
+ while (p->token != '}') {
+ if (layout->count == FIELDS) return reject(p, "layout exceeds 16 fields");
+ if (layout->tail) return reject(p, "variable bytes must be the last field");
+ if (p->token != NAME) return reject(p, "expected a field name");
+ for (size_t i = 0; i < layout->count; ++i)
+ if (!strcmp(layout->fields[i].name, p->name)) return reject(p, "duplicate field");
+ Field *f = &layout->fields[layout->count];
+ strcpy(f->name, p->name);
+ f->offset = layout->prefix;
+ if (!next(p) || !token(p, ':')) return false;
+ if (is_word(p, "u32le")) {
+ f->number = true;
+ f->length = 4;
+ if (!next(p)) return false;
+ } else if (is_word(p, "bytes")) {
+ if (!next(p)) return false;
+ if (p->token == '[') {
+ if (!next(p)) return false;
+ if (p->token != NUMBER) return reject(p, "fixed bytes requires a constant size");
+ f->length = p->number;
+ if (!next(p) || !token(p, ']')) return false;
+ } else { f->tail = true; layout->tail = true; }
+ } else return reject(p, "supported field types: u32le, bytes[N], bytes");
+ if (f->length > PURE_OBJECT_LIMIT - layout->prefix) return reject(p, "layout exceeds object bound");
+ layout->prefix += f->length;
+ ++layout->count;
+ if (!token(p, ';')) return false;
+ }
+ if (!layout->count) return reject(p, "empty layout");
+ ++p->layout_count;
+ return token(p, '}');
+}
+
+static bool reference(Parser *p, Symbol *out) {
+ if (is_word(p, "request")) {
+ if (!p->put) return reject(p, "request.body is only available in on put");
+ *out = (Symbol){.kind = BYTE_VALUE, .region = {.to_end = true}};
+ return field(p, "request", "body");
+ }
+ Symbol *symbol = p->token == NAME ? find(p, p->name) : NULL;
+ if (!symbol) return reject(p, "unknown value");
+ *out = *symbol;
+ if (!next(p)) return false;
+ if (p->token != '.') return true;
+ if (!next(p)) return false;
+ if (symbol->kind == RESULT_VALUE) {
+ if (p->put) return reject(p, "write result has no body; use the input value");
+ *out = (Symbol){.kind = BYTE_VALUE, .region = {.to_end = true}};
+ return word(p, "body");
+ }
+ if (symbol->kind != LAYOUT_VALUE || p->token != NAME) return reject(p, "expected a layout field");
+ Layout *layout = &p->layouts[symbol->layout];
+ Field *f = NULL;
+ for (size_t i = 0; i < layout->count; ++i)
+ if (!strcmp(p->name, layout->fields[i].name)) f = &layout->fields[i];
+ if (!f) return reject(p, "unknown layout field");
+ size_t offset = symbol->region.offset + f->offset;
+ *out = (Symbol){.kind = f->number ? INDEX_VALUE : BYTE_VALUE};
+ if (f->number) out->index = (PureIndex){.value = offset, .from_u32le = true};
+ else out->region = (PureRegion){.offset = offset,
+ .length = f->tail ? (symbol->region.to_end ? 0 : symbol->region.length - f->offset) : f->length,
+ .to_end = f->tail && symbol->region.to_end};
+ return next(p);
+}
+
+static bool byte_reference(Parser *p, Symbol *out) {
+ return reference(p, out) && require_bytes(p, out);
+}
+
+static bool index_value(Parser *p, PureIndex *out) {
+ if (p->token == NUMBER) {
+ *out = (PureIndex){.value = p->number};
+ return next(p);
+ }
+ Symbol value;
+ if (!reference(p, &value)) return false;
+ if (value.kind != INDEX_VALUE) return reject(p, "range requires an integer or u32le field");
+ *out = value.index;
+ return true;
+}
+
+static bool layout_view(Parser *p, Symbol *out) {
+ if (!next(p) || !token(p, '(')) return false;
+ Layout *layout = p->token == NAME ? find_layout(p, p->name) : NULL;
+ if (!layout) return reject(p, "unknown layout");
+ if (!next(p) || !token(p, ',')) return false;
+ Symbol source;
+ if (!byte_reference(p, &source) || !token(p, ')')) return false;
+ if (source.step) return reject(p, "layout view requires a statically located source");
+ size_t bound = source.region.to_end ? PURE_OBJECT_LIMIT - source.region.offset : source.region.length;
+ if (layout->prefix > bound) return reject(p, "layout exceeds source bound");
+ require_length(p, source.region.offset + layout->prefix);
+ *out = (Symbol){.kind = LAYOUT_VALUE, .region = source.region, .layout = (size_t)(layout - p->layouts)};
+ if (!layout->tail) { out->region.length = layout->prefix; out->region.to_end = false; }
+ return true;
+}
+
+static bool view(Parser *p, Symbol *out) {
+ if (is_word(p, "view")) return layout_view(p, out);
+ if (!is_word(p, "range")) return reference(p, out);
+ Symbol parent;
+ PureIndex offset, length;
+ if (!next(p) || !token(p, '(') || !byte_reference(p, &parent) || !token(p, ',') ||
+ !index_value(p, &offset) || !token(p, ',') || !index_value(p, &length) || !token(p, ')')) return false;
+ bool dynamic = parent.step || offset.from_u32le || length.from_u32le;
+ *out = (Symbol){.kind = BYTE_VALUE};
+ if (dynamic) {
+ if (!p->put) return reject(p, "data-dependent ranges currently require PUT input");
+ if (p->program.input_steps == PURE_DYNAMIC_LIMIT) return reject(p, "input exceeds 8 dynamic ranges");
+ if ((!offset.from_u32le && offset.value > PURE_OBJECT_LIMIT) ||
+ (!length.from_u32le && length.value > PURE_OBJECT_LIMIT)) return reject(p, "range exceeds object bound");
+ PureRangeStep *step = &p->program.steps[p->program.input_steps++];
+ *step = (PureRangeStep){.source = parent.region, .source_step = parent.step,
+ .offset = offset, .length = length};
+ out->step = p->program.input_steps;
+ } else {
+ size_t bound = parent.region.to_end ? PURE_OBJECT_LIMIT - parent.region.offset : parent.region.length;
+ if (offset.value > bound || length.value > bound - offset.value) return reject(p, "range exceeds its source bound");
+ out->region = (PureRegion){.offset = parent.region.offset + offset.value, .length = length.value};
+ require_length(p, out->region.offset + out->region.length);
+ }
+ ++p->program.range_definitions;
+ return true;
+}
+
+static bool effect(Parser *p, Symbol *out) {
+ if (p->effect) return reject(p, "only one storage effect is supported per handler");
+ if (!word(p, "store") || !token(p, '.')) return false;
+ bool splice = p->put && is_word(p, "splice");
+ if (!word(p, p->put ? (splice ? "splice" : "write") : "read") ||
+ !token(p, '(') || !field(p, "request", "key")) return false;
+ if (p->put) {
+ Symbol value;
+ if (!token(p, ',') || !field(p, "request", "revision") || !token(p, ',')) return false;
+ if (splice) {
+ if (!index_value(p, &p->program.splice_offset) || !token(p, ',') ||
+ !index_value(p, &p->program.splice_remove) || !token(p, ',')) return false;
+ if ((!p->program.splice_offset.from_u32le && p->program.splice_offset.value > PURE_OBJECT_LIMIT) ||
+ (!p->program.splice_remove.from_u32le && p->program.splice_remove.value > PURE_OBJECT_LIMIT))
+ return reject(p, "splice exceeds object bound");
+ p->program.splice = true;
+ }
+ if (!byte_reference(p, &value)) return false;
+ p->program.write = value.region;
+ p->program.write_step = value.step;
+ if (splice && p->token == ',') {
+ if (!next(p)) return false;
+ if (p->token != NUMBER || p->number > PURE_OBJECT_LIMIT)
+ return reject(p, "splice limit requires a constant within the object bound");
+ p->program.splice_limit = (uint32_t)p->number;
+ if (!next(p)) return false;
+ }
+ }
+ if (!token(p, ')')) return false;
+ out->kind = RESULT_VALUE;
+ p->effect = true;
+ return true;
+}
+
+static bool handler(Parser *p) {
+ p->count = 0;
+ p->effect = false;
+ if (!token(p, '{')) return false;
+ while (is_word(p, "let")) {
+ if (p->put && p->effect) return reject(p, "all views must precede the storage effect; reply must follow it");
+ if (p->count == SYMBOLS) return reject(p, "handler exceeds 32 definitions");
+ if (!next(p)) return false;
+ if (p->token != NAME || is_word(p, "request") || is_word(p, "store") ||
+ is_word(p, "range") || is_word(p, "view")) return reject(p, "expected a non-reserved definition name");
+ if (find(p, p->name)) return reject(p, "duplicate definition");
+ char name[32];
+ strcpy(name, p->name);
+ Symbol symbol = {0};
+ if (!next(p) || !token(p, '=')) return false;
+ if (is_word(p, "store")) {
+ if (!effect(p, &symbol)) return false;
+ } else {
+ if (!view(p, &symbol)) return false;
+ ++p->program.view_definitions;
+ }
+ if (!token(p, ';')) return false;
+ strcpy(symbol.name, name);
+ p->symbols[p->count++] = symbol;
+ }
+ if (!p->effect) return reject(p, "handler requires its storage effect");
+ if (!word(p, "reply") || !token(p, '(')) return false;
+ Symbol *result = p->token == NAME ? find(p, p->name) : NULL;
+ if (!result || result->kind != RESULT_VALUE) return reject(p, "reply requires this handler's storage result");
+ if (!next(p)) return false;
+ Symbol body = {0};
+ bool has_body = p->token == ',';
+ if (has_body && (!next(p) || !byte_reference(p, &body))) return false;
+ if (!token(p, ')') || !token(p, ';') || !token(p, '}')) return false;
+ if (p->put) {
+ p->program.reply = body.region;
+ p->program.reply_step = body.step;
+ p->program.reply_input = has_body;
+ } else p->program.read = body.region;
+ return true;
+}
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size) {
+ Parser p = {.source = source, .length = length, .line = 1, .token_line = 1,
+ .error = error, .error_size = error_size,
+ .program.splice_limit = PURE_OBJECT_LIMIT};
+ if (error_size) error[0] = 0;
+ if (length > PURE_PROGRAM_LIMIT) return reject(&p, "program exceeds 16 KiB");
+ if (!next(&p)) return false;
+ while (is_word(&p, "layout")) if (!layout_definition(&p)) return false;
+ unsigned handlers = 0;
+ while (p.token) {
+ if (!word(&p, "on")) return false;
+ if (!is_word(&p, "get") && !is_word(&p, "put")) return reject(&p, "expected get or put handler");
+ p.put = is_word(&p, "put");
+ unsigned bit = p.put ? 2 : 1;
+ if (handlers & bit) return reject(&p, "duplicate handler");
+ handlers |= bit;
+ if (!next(&p) || !handler(&p)) return false;
+ }
+ if (handlers != 3) return reject(&p, "both get and put handlers are required");
+ *out = p.program; /* Invalid preparation never changes the installed plan. */
+ return true;
+}
+
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size) {
+ FILE *file = fopen(path, "rb");
+ if (!file) {
+ if (error_size) snprintf(error, error_size, "cannot open program");
+ return false;
+ }
+ char source[PURE_PROGRAM_LIMIT + 1];
+ size_t length = fread(source, 1, sizeof(source), file);
+ bool bad = ferror(file) != 0;
+ if (fclose(file)) bad = true;
+ if (bad) {
+ if (error_size) snprintf(error, error_size, "cannot read program");
+ return false;
+ }
+ return pure_program_parse(source, length, out, error, error_size);
+}
diff --git a/prototypes/connections/program.h b/prototypes/connections/program.h
new file mode 100644
index 0000000..078a382
--- /dev/null
+++ b/prototypes/connections/program.h
@@ -0,0 +1,50 @@
+#ifndef PURE_PROGRAM_H
+#define PURE_PROGRAM_H
+#include "flow.h"
+#include <stdint.h>
+
+#define PURE_PROGRAM_LIMIT 16384u
+#define PURE_DYNAMIC_LIMIT 8u
+typedef struct {
+ size_t offset, length;
+ bool to_end;
+} PureRegion;
+
+typedef struct { size_t value; bool from_u32le; } PureIndex;
+typedef struct {
+ PureRegion source;
+ size_t source_step; /* 0: source region; otherwise a preceding step + 1. */
+ PureIndex offset, length;
+} PureRangeStep;
+
+/* Prepared connections, not an instruction stream. All view definitions are
+ * checked at preparation; their root-length requirements survive elimination.
+ * Input views are evaluated before the write effect. A read still opens and
+ * validates the object even if its response has no body. */
+typedef struct {
+ PureRegion read, write, reply;
+ size_t read_required, input_required;
+ size_t view_definitions, range_definitions;
+ size_t write_step, reply_step, input_steps;
+ PureRangeStep steps[PURE_DYNAMIC_LIMIT];
+ bool reply_input;
+ bool splice;
+ uint32_t splice_limit; /* Final stored bytes; checked under the writer lock. */
+ PureIndex splice_offset, splice_remove;
+} PureProgram;
+
+#if SIZE_MAX == UINT64_MAX
+_Static_assert(sizeof(PureProgram) == 680, "prepared document definition grew");
+#endif
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size);
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size);
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out);
+/* Validates all input views, including unused dynamic views, before any effect.
+ * Returns borrowed selections; their lifetime remains that of source. */
+bool pure_program_input(const PureProgram *, PureSpan source, PureSpan *write, PureSpan *reply);
+/* Byte positions in the stored value. Bounds against the current version are
+ * checked by the conditional storage effect under the writer lock. */
+bool pure_program_splice(const PureProgram *, PureSpan source, size_t *offset, size_t *remove);
+#endif
diff --git a/prototypes/connections/result.h b/prototypes/connections/result.h
new file mode 100644
index 0000000..8abb0f2
--- /dev/null
+++ b/prototypes/connections/result.h
@@ -0,0 +1,8 @@
+#ifndef PURE_RESULT_H
+#define PURE_RESULT_H
+typedef enum {
+ PURE_OK, PURE_NOT_FOUND, PURE_CONFLICT, PURE_BUSY, PURE_BUDGET,
+ PURE_LIMIT, PURE_STORE_ERROR, PURE_UNCERTAIN,
+ PURE_INVALID, PURE_DENIED, PURE_CLOSED, PURE_CANCELLED, PURE_ALLOCATION
+} PureResult;
+#endif
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/README.md b/prototypes/connections/results/2026-09-23-byte-storage/README.md
new file mode 100644
index 0000000..f28229b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/README.md
@@ -0,0 +1,31 @@
+# 019 검증 자료
+
+> 작성 기능 도입 후 검증은 [020](../2026-09-23-prepared-connections/README.md)에 있다.
+> 이 디렉터리의 소스·결과는 도입 전 기록으로 보존한다.
+
+SQL 의존성을 제거한 C17/POSIX 저장 경로와 실제 루프백 TCP·기존 Workbench CLI의
+기능·수명 검사다. 시간·처리량·전체 RSS 비교는 수행하지 않았다.
+
+- [native.json](native.json): 일반 빌드의 16개 통합 시나리오, 종료 시 자원 수, 환경·소스·실행 파일 해시.
+- [sanitized.json](sanitized.json): ASan·UBSan 빌드의 같은 시나리오. 누수 검사를 끄지 않았다.
+- [verification.json](verification.json): 명령, 단위 검사 결과, 링크 의존성, 소스 사본·실행 파일 일치 확인.
+- `sources/`: 결과에 기록된 소스·Wasm 사본. 이후 작업 트리가 바뀌면 이 파일들을 별도 작업 트리에 사용한다.
+
+단위 검사는 필요한 범위만 읽기, 갱신 중 이전 참조, 공개 전후 오류, 공개 전 자식 프로세스
+종료 등을 포함한다. 처음 검사한 범위 fixture는 4 KiB를 가정했으나 현재 환경은 16 KiB
+페이지였다. 최종 검사는 실제 OS 페이지 크기를 사용해 페이지 경계를 넘고, 서로 다른
+페이지의 잘못된 참조도 구분할 수 있는 데이터로 수정했다. 초기 실행 결과는 `initial/`에
+보존했다. 그때와 최종 소스의 유일한 차이는 `initial/test-flow.c`이며, 기록의 해시와 맞는다.
+성능 비교 자료로 사용하지 않는다.
+
+전원 장애나 실제 디스크 고장을 재현한 것은 아니다. fsync 전후의 실패 주입과 프로세스
+종료를 검사했다. 본문 예산은 논리적인 보유 바이트 수이며 매핑·페이지 캐시·디스크·소켓·
+클라이언트 메모리를 합친 상한이 아니다. 전송 시점에 따라 수신 접두부 복사량과 쓰기 경쟁의
+승자가 바뀔 수 있으므로 빌드 간 진단 수치의 차이를 최적화 결과로 해석하지 않는다.
+
+재현은 [구현 README](../../README.md)의 `make check` 명령을 따른다.
+`EVIDENCE=/새/경로.json`을 추가하면 새 파일로 기록하며 기존 자료는 덮어쓰지 않는다.
+이 환경에서는 소켓·자식 프로세스·LeakSanitizer의 샌드박스 제한 때문에 승인된 환경에서
+실행했다. 외부 서비스는 사용하지 않았다. macOS 실행은 아직 확인하지 않았다.
+
+이전 SQLite 경로의 자료는 [018](../2026-09-23-native-connections/README.md)에 별도로 있다.
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/initial/native.json b/prototypes/connections/results/2026-09-23-byte-storage/initial/native.json
new file mode 100644
index 0000000..450a8ac
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/initial/native.json
@@ -0,0 +1,116 @@
+{
+ "kind": "native-byte-path-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines"
+ ],
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 11,
+ "gets": 14,
+ "conflicts": 5,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115417,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39176
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "binary_sha256": "2f8c664c61f0ea0a26574530c165a7fdff1058902b9938e73d146927b1fd44eb",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "9b88dfd664bf85e3fd1e971bf5d1b5bd408f6c2a069ffd02d41c05973d8cd2dd",
+ "prototypes/connections/store.h": "8675d39a02558b8f877477b3715e15816d12f4b4864eda19a63635941503c774",
+ "prototypes/connections/server.c": "e85b6d7f91e14eed6b22a4615654c33e9cc3163020ffa80fbd201f8f055eb3c2",
+ "prototypes/connections/check.py": "30363c718294540fbc653223fdf2a07dbcafbfa8bf1470aa5704a33ce0ea2b01",
+ "prototypes/connections/test-flow.c": "e209f1d76e076d5f1a680908bbfbfb0b07efc79ec99b308e544fe3902ef26d05",
+ "prototypes/connections/Makefile": "82995e6c3eda516c2fae02d680dff90371fb595edc2c5c9d4b3e5fd05137d36b",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/initial/sanitized.json b/prototypes/connections/results/2026-09-23-byte-storage/initial/sanitized.json
new file mode 100644
index 0000000..b1d57b3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/initial/sanitized.json
@@ -0,0 +1,116 @@
+{
+ "kind": "native-byte-path-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines"
+ ],
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39176
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "binary_sha256": "bd016cc93b1bd2a9c01d7f84bcc212e049b28e41528d52a90bdb70fb13100cb1",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "9b88dfd664bf85e3fd1e971bf5d1b5bd408f6c2a069ffd02d41c05973d8cd2dd",
+ "prototypes/connections/store.h": "8675d39a02558b8f877477b3715e15816d12f4b4864eda19a63635941503c774",
+ "prototypes/connections/server.c": "e85b6d7f91e14eed6b22a4615654c33e9cc3163020ffa80fbd201f8f055eb3c2",
+ "prototypes/connections/check.py": "30363c718294540fbc653223fdf2a07dbcafbfa8bf1470aa5704a33ce0ea2b01",
+ "prototypes/connections/test-flow.c": "e209f1d76e076d5f1a680908bbfbfb0b07efc79ec99b308e544fe3902ef26d05",
+ "prototypes/connections/Makefile": "82995e6c3eda516c2fae02d680dff90371fb595edc2c5c9d4b3e5fd05137d36b",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/initial/test-flow.c b/prototypes/connections/results/2026-09-23-byte-storage/initial/test-flow.c
new file mode 100644
index 0000000..23798b4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/initial/test-flow.c
@@ -0,0 +1,178 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static int failed_stage = -1;
+static bool crash_at_stage;
+int pure_store_test_fault(PureStoreStage stage) {
+ if ((int)stage != failed_stage) return 0;
+ if (crash_at_stage) _exit(77);
+ return 1;
+}
+typedef struct { unsigned char *bytes; unsigned releases; } Owner;
+static void release(void *raw) {
+ Owner *owner = raw;
+ free(owner->bytes);
+ owner->bytes = NULL;
+ ++owner->releases;
+}
+
+static void transfers(void) {
+ Owner owner = {.bytes = malloc(5)};
+ CHECK(owner.bytes);
+ memcpy(owner.bytes, "a\0bcd", 5);
+ PureTransfer transfer = {0};
+ pure_transfer_init(&transfer, (PureSpan){(const unsigned char *)"head", 4},
+ (PureSpan){owner.bytes, 5}, &owner, release);
+ CHECK(!pure_transfer_consume(&transfer, 5));
+ CHECK(transfer.active && !owner.releases);
+ CHECK(pure_transfer_consume(&transfer, 0));
+ unsigned char received[9];
+ size_t used = 0;
+ while (transfer.active) {
+ PureSpan span = pure_transfer_next(&transfer, 2);
+ CHECK(span.size && span.size <= 2);
+ memcpy(received + used, span.data, span.size);
+ used += span.size;
+ CHECK(pure_transfer_consume(&transfer, span.size));
+ CHECK((used == 9) == (owner.releases == 1));
+ }
+ CHECK(used == 9 && !memcmp(received, "heada\0bcd", 9));
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 1 && !pure_transfer_consume(&transfer, 0));
+ owner.bytes = malloc(3);
+ CHECK(owner.bytes);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){owner.bytes, 3}, &owner, release);
+ CHECK(pure_transfer_consume(&transfer, 1));
+ pure_transfer_abort(&transfer);
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 2 && !transfer.active);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){0}, &owner, release);
+ CHECK(owner.releases == 3 && !transfer.active);
+}
+
+static void storage(const char *path) {
+ CHECK(pure_store_init(path) == PURE_OK);
+ PureStoredView first, second;
+ CHECK(pure_store_get(path, "missing", 100, &first) == PURE_NOT_FOUND);
+ CHECK(!first.mapping && !first.mapped_size);
+ static const unsigned char original[] = {0, 1, 2, 255, 17};
+ static const unsigned char updated[] = {9, 8, 7};
+ int64_t revision;
+ CHECK(pure_store_put(path, "work", 0, (PureSpan){original, sizeof(original)}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ CHECK(pure_store_get(path, "work", sizeof(original) - 1, &first) == PURE_BUDGET);
+ CHECK(!first.mapping && !first.mapped_size);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 3, &first) == PURE_OK);
+ CHECK(first.object_size == sizeof(original) && first.body.size == 3 && !memcmp(first.body.data, original + 1, 3));
+ pure_store_release(&first);
+ CHECK(pure_store_get_range(path, "work", SIZE_MAX, 1, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, SIZE_MAX, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 2, &first) == PURE_BUDGET);
+ CHECK(pure_store_get_range(path, "work", sizeof(original), 0, 0, &first) == PURE_OK);
+ CHECK(!first.mapped_size && !first.body.size);
+ pure_store_release(&first);
+ CHECK(pure_store_get(path, "work", sizeof(original), &first) == PURE_OK);
+ CHECK(first.body.size == sizeof(original) && first.revision == 1);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 2);
+ CHECK(!memcmp(first.body.data, original, sizeof(original)));
+ CHECK(pure_store_get(path, "work", 100, &second) == PURE_OK);
+ CHECK(second.revision == 2 && second.body.size == sizeof(updated));
+ CHECK(!memcmp(second.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ pure_store_release(&first);
+ pure_store_release(&second);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){original, sizeof(original)}, &revision) == PURE_CONFLICT);
+ CHECK(revision == 2);
+
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 2 && !memcmp(first.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == 3);
+ failed_stage = -1;
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_CONFLICT);
+
+ /* A crashed unpublished writer leaves only a private file. A new publisher
+ * must still use the previous committed version, never an incomplete body. */
+ pid_t child = fork();
+ CHECK(child >= 0);
+ if (!child) {
+ failed_stage = PURE_AFTER_HEADER;
+ crash_at_stage = true;
+ pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision);
+ _exit(78);
+ }
+ int status;
+ CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 77);
+ CHECK(pure_store_init(path) == PURE_OK);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 4);
+
+ char file[320];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ CHECK(fd >= 0);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_put(path, "work", INT64_MAX, (PureSpan){original, sizeof(original)}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_put(path, "empty", 0, (PureSpan){0}, &revision) == PURE_OK);
+ CHECK(pure_store_get(path, "empty", 0, &first) == PURE_OK && first.body.size == 0);
+ pure_store_release(&first);
+
+ /* Range mapping crosses page boundaries without copying a whole object. */
+ unsigned char bytes[12288];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)i;
+ CHECK(pure_store_put(path, "range", 0, (PureSpan){bytes, sizeof(bytes)}, &revision) == PURE_OK);
+ CHECK(pure_store_get_range(path, "range", 4079, 4201, 4201, &first) == PURE_OK);
+ CHECK(first.body.size == 4201 && !memcmp(first.body.data, bytes + 4079, 4201));
+ pure_store_release(&first);
+ snprintf(file, sizeof(file), "%s/obj-broken", path);
+ fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0600);
+ CHECK(fd >= 0 && write(fd, "incomplete", 10) == 10 && close(fd) == 0);
+ CHECK(pure_store_get(path, "broken", 100, &first) == PURE_STORE_ERROR && !first.mapped_size);
+ CHECK(pure_store_put(path, "broken", 0, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_init(file) == PURE_STORE_ERROR);
+ struct stat info;
+ CHECK(stat(file, &info) == 0 && info.st_size == 10);
+}
+
+int main(void) {
+ transfers();
+ char directory[] = "/tmp/pure-connection-unit-XXXXXX";
+ CHECK(mkdtemp(directory));
+ char path[256];
+ snprintf(path, sizeof(path), "%s/store", directory);
+ storage(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ CHECK(rmdir(directory) == 0);
+ puts("{\"transfer\":\"partial-consumption-and-single-release\","
+ "\"storage\":\"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty\"}");
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/native.json b/prototypes/connections/results/2026-09-23-byte-storage/native.json
new file mode 100644
index 0000000..52bea4c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/native.json
@@ -0,0 +1,116 @@
+{
+ "kind": "native-byte-path-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines"
+ ],
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39176
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "binary_sha256": "2f8c664c61f0ea0a26574530c165a7fdff1058902b9938e73d146927b1fd44eb",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "9b88dfd664bf85e3fd1e971bf5d1b5bd408f6c2a069ffd02d41c05973d8cd2dd",
+ "prototypes/connections/store.h": "8675d39a02558b8f877477b3715e15816d12f4b4864eda19a63635941503c774",
+ "prototypes/connections/server.c": "e85b6d7f91e14eed6b22a4615654c33e9cc3163020ffa80fbd201f8f055eb3c2",
+ "prototypes/connections/check.py": "30363c718294540fbc653223fdf2a07dbcafbfa8bf1470aa5704a33ce0ea2b01",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/Makefile": "82995e6c3eda516c2fae02d680dff90371fb595edc2c5c9d4b3e5fd05137d36b",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sanitized.json b/prototypes/connections/results/2026-09-23-byte-storage/sanitized.json
new file mode 100644
index 0000000..e2db165
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sanitized.json
@@ -0,0 +1,116 @@
+{
+ "kind": "native-byte-path-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines"
+ ],
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39176
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39176
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "binary_sha256": "bd016cc93b1bd2a9c01d7f84bcc212e049b28e41528d52a90bdb70fb13100cb1",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "9b88dfd664bf85e3fd1e971bf5d1b5bd408f6c2a069ffd02d41c05973d8cd2dd",
+ "prototypes/connections/store.h": "8675d39a02558b8f877477b3715e15816d12f4b4864eda19a63635941503c774",
+ "prototypes/connections/server.c": "e85b6d7f91e14eed6b22a4615654c33e9cc3163020ffa80fbd201f8f055eb3c2",
+ "prototypes/connections/check.py": "30363c718294540fbc653223fdf2a07dbcafbfa8bf1470aa5704a33ce0ea2b01",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/Makefile": "82995e6c3eda516c2fae02d680dff90371fb595edc2c5c9d4b3e5fd05137d36b",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/Makefile b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/Makefile
new file mode 100644
index 0000000..5f5005b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/Makefile
@@ -0,0 +1,20 @@
+CC ?= cc
+CFLAGS ?= -O2 -g
+CFLAGS += -std=c17 -Wall -Wextra -Wpedantic -Werror
+BUILD ?= build
+
+.PHONY: all check
+all: $(BUILD)/pure-connections
+
+$(BUILD):
+ mkdir -p $@
+
+$(BUILD)/pure-connections: server.c store.c flow.c store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) server.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-flow: test-flow.c store.c flow.c store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_STORE_TEST test-flow.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+check: $(BUILD)/test-flow $(BUILD)/pure-connections
+ $(BUILD)/test-flow
+ python3 check.py --server $(BUILD)/pure-connections $(if $(EVIDENCE),--output "$(EVIDENCE)")
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/check.py b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/check.py
new file mode 100644
index 0000000..1d7b403
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/check.py
@@ -0,0 +1,317 @@
+#!/usr/bin/env python3
+"""Exercise local TCP, immutable byte extents, and the existing workbench CLI."""
+import argparse
+from contextlib import contextmanager
+from concurrent.futures import ThreadPoolExecutor
+import fcntl
+import hashlib
+import http.client
+import json
+import platform
+from pathlib import Path
+import select
+import socket
+import struct
+import subprocess
+import tempfile
+import time
+
+ROOT = Path(__file__).resolve().parent
+WORKBENCH = ROOT.parent / 'workbench'
+OBJECT_LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+class Server:
+ def __init__(self, binary, storage, budget=4 * 1024 * 1024, timeout=5000):
+ self.process = subprocess.Popen([str(binary), '--store', str(storage), '--port', '0',
+ '--budget', str(budget), '--timeout-ms', str(timeout), '--send-buffer', '4096'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
+ if not select.select([self.process.stdout], [], [], 15)[0]:
+ self.process.kill()
+ raise AssertionError('server readiness timed out')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.ready = json.loads(line)
+ self.port = self.ready['port']
+ self.stats = None
+
+ def close(self):
+ if self.process.poll() is None:
+ self.process.terminate()
+ try:
+ stdout, stderr = self.process.communicate(timeout=10)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.process.communicate()
+ raise
+ assert self.process.returncode == 0, (stdout, stderr)
+ self.stats = json.loads(stderr)
+ assert self.stats['active'] == self.stats['retained_payload_bytes'] == 0
+ assert self.stats['peak_retained_payload_bytes'] <= self.stats['payload_budget']
+ assert self.stats['peak_connections'] <= 8
+
+
+@contextmanager
+def serving(*args, **kwargs):
+ server = Server(*args, **kwargs)
+ try:
+ yield server
+ finally:
+ server.close()
+
+
+def rpc(server, method, key, body=b'', expected=None):
+ headers = {'Content-Length': str(len(body))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = '*' if expected == 0 else f'"{expected}"'
+ connection = http.client.HTTPConnection('127.0.0.1', server.port, timeout=8)
+ try:
+ connection.request(method, f'/objects/{key}', body, headers)
+ response = connection.getresponse()
+ return response.status, dict(response.getheaders()), response.read()
+ finally:
+ connection.close()
+
+
+def wire(server, request, chunks=None):
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ if chunks:
+ for chunk in chunks:
+ sock.sendall(chunk)
+ else:
+ sock.sendall(request)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ return response.status, dict(response.getheaders()), response.read()
+
+
+def header(method, key, size=0, condition=b''):
+ return (f'{method} /objects/{key} HTTP/1.1\r\nHost: localhost\r\n'
+ f'Content-Length: {size}\r\n'.encode() + condition + b'\r\n')
+
+
+def cli(server, commands, source=None, expected_code=0):
+ result = subprocess.run(['node', str(WORKBENCH / 'cli.mjs'), *([str(source)] if source else [])],
+ input=commands.replace('$URL', f'http://127.0.0.1:{server.port}'), text=True,
+ capture_output=True, timeout=30)
+ assert result.returncode == expected_code, (result.stdout, result.stderr)
+ return [json.loads(line) for line in result.stdout.splitlines()], result.stderr
+
+
+def check(binary, directory):
+ storage = directory / 'objects'
+ checks, records = [], []
+ with serving(binary, storage) as server:
+ assert rpc(server, 'GET', 'absent')[0] == 404
+ payload = b'\x00\xffbinary\r\n\r\n' + bytes(range(256)) * 41
+ request = header('PUT', 'binary', len(payload), b'If-None-Match: *\r\n') + payload
+ status, headers, _ = wire(server, request, [request[:7], request[7:51], request[51:57], request[57:]])
+ assert status == 200 and headers['ETag'] == '"1"'
+ assert rpc(server, 'GET', 'binary')[2] == payload
+ checks.append('fragmented request and binary bytes round trip')
+ assert rpc(server, 'PUT', 'binary', b'new', 0)[0] == 412
+ assert rpc(server, 'PUT', 'binary', b'new', 1)[0] == 200
+ assert rpc(server, 'PUT', 'binary', b'stale', 1)[0] == 412
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('conditional create and stale revision preserve committed bytes')
+
+ with (storage / '.writer.lock').open('r+b') as lock:
+ fcntl.lockf(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ assert rpc(server, 'PUT', 'binary', b'blocked', 2)[0] == 503
+ fcntl.lockf(lock, fcntl.LOCK_UN)
+ broken = storage / 'obj-broken'
+ broken.write_bytes(b'incomplete')
+ assert rpc(server, 'GET', 'broken')[0] == 500
+ assert rpc(server, 'PUT', 'broken', b'failure', 0)[0] == 500
+ assert broken.read_bytes() == b'incomplete'
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('writer contention and invalid extent fail without overwriting data')
+
+ with serving(binary, storage) as second_writer:
+ with ThreadPoolExecutor(max_workers=2) as pool:
+ tasks = [pool.submit(rpc, target, 'PUT', 'race', value, 0)
+ for target, value in [(server, b'first'), (second_writer, b'second')]]
+ statuses = [task.result()[0] for task in tasks]
+ assert statuses.count(200) == 1 and all(status in [200, 412, 503] for status in statuses)
+ status, headers, body = rpc(server, 'GET', 'race')
+ assert status == 200 and headers['ETag'] == '"1"' and body in [b'first', b'second']
+ records.append(second_writer.stats)
+ checks.append('two native writers cannot both create the same expected revision')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'incomplete', 100, b'If-None-Match: *\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ sock.close()
+ assert rpc(server, 'GET', 'incomplete')[0] == 404
+ checks.append('incomplete request never commits and releases its allocation')
+
+ # Force genuine partial socket sends. A write on another connection must
+ # not alter the immutable file whose bytes are still being transmitted.
+ large = bytes(range(256)) * 4096
+ assert rpc(server, 'PUT', 'large', large, 0)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.getheader('ETag') == '"1"'
+ assert response.read(17) == large[:17]
+ assert rpc(server, 'PUT', 'large', b'changed', 1)[0] == 200
+ assert response.read() == large[17:]
+ sock.close()
+ assert rpc(server, 'GET', 'large')[2] == b'changed'
+ checks.append('borrowed read remains the same snapshot during another commit')
+
+ assert rpc(server, 'PUT', 'large', large, 2)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ assert sock.recv(1)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ sock.close()
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('receiver reset aborts an outstanding borrowed transfer')
+
+ assert wire(server, header('PUT', 'too_large', OBJECT_LIMIT + 1, b'If-None-Match: *\r\n'))[0] == 413
+ malformed = [
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nContent-Length: 1\r\nContent-Length: 1\r\nIf-None-Match: *\r\n\r\nx',
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n',
+ b'GET /objects/bad HTTP/1.1\r\nHost: x\x00hidden\r\n\r\n',
+ ]
+ for request in malformed:
+ assert wire(server, request)[0] == 400
+ assert rpc(server, 'GET', 'bad')[0] == 404
+ checks.append('unsupported framing and oversized payload are rejected before effects')
+
+ # Existing authoring path: define, manipulate, save remotely, reconstruct
+ # in a fresh runtime. No fabricated project fixture or mock storage.
+ source = WORKBENCH / 'examples' / 'direct.pure'
+ saved = directory / 'restored.json'
+ lines, _ = cli(server, 'point drag down 80 180\npoint drag move 210 210\npoint drag up 210 210\n'
+ 'connect $URL authored\npush 0\nquit\n', source)
+ snapshots = [line for line in lines if 'states' in line]
+ assert snapshots
+ expected_states = snapshots[-1]['states']
+ assert expected_states['x'] == 210 and expected_states['y'] == 190 and expected_states['dragging'] == 0
+ lines, _ = cli(server, f'connect $URL authored\npull\nsave-project {saved}\nquit\n')
+ assert [line for line in lines if 'states' in line][-1]['states'] == expected_states
+ document = json.loads(saved.read_text())
+ assert document['version'] == 2 and document['source'] == source.read_text()
+ lines, error = cli(server, 'connect $URL authored\npush 0\nquit\n', source, 1)
+ assert '412' in error
+ checks.append('existing workbench manipulation restores in a fresh runtime and reports conflict')
+
+ assert rpc(server, 'PUT', 'invalid_project', b'{"format":"pure-workbench","version":2,"source":"state x=1","states":[]}', 0)[0] == 200
+ lines, error = cli(server, 'show\nconnect $URL invalid_project\npull\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and error
+ lines, error = cli(server, 'point drag down 90 170\nconnect $URL authored\npull\npush\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and states[-1]['dragging'] == 1
+ assert len(error.strip().splitlines()) == 2
+ checks.append('invalid or non-idle restore preserves local state and does not adopt remote revision')
+
+ assert rpc(server, 'PUT', 'wide_revision', rpc_bytes(saved), 0)[0] == 200
+ wide = storage / 'obj-wide_revision'
+ raw = wide.read_bytes()
+ wide.write_bytes(raw[:8] + struct.pack('<Q', 9007199254740993) + raw[16:])
+ lines, _ = cli(server, 'connect $URL wide_revision\npull\npush\nquit\n')
+ revisions = [line['revision'] for line in lines if 'remote' in line and 'revision' in line]
+ assert revisions == ['9007199254740993', '9007199254740994']
+ checks.append('revision above JavaScript safe integer round trips without numeric coercion')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'unread_ack', 4, b'If-None-Match: *\r\n') + b'done')
+ try:
+ deadline = time.monotonic() + 3
+ while True:
+ committed = storage / 'obj-unread_ack'
+ if committed.exists():
+ assert committed.read_bytes()[24:] == b'done'
+ break
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ finally:
+ sock.close() # Client never consumes the successful response.
+ assert rpc(server, 'PUT', 'unread_ack', b'again', 0)[0] == 412
+ assert rpc(server, 'GET', 'unread_ack')[2] == b'done'
+ checks.append('unread acknowledgment does not undo commit or permit a stale retry')
+
+ # A disconnect after commit can hide the ACK; retries remain conditional.
+ assert rpc(server, 'PUT', 'empty', b'', 0)[0] == 200
+ assert rpc(server, 'GET', 'empty')[2] == b''
+ checks.append('empty body has a valid lifetime and stored revision')
+ records.append(server.stats)
+
+ with serving(binary, storage) as restarted:
+ assert rpc(restarted, 'GET', 'binary')[2] == b'new'
+ assert rpc(restarted, 'GET', 'authored')[2] == rpc_bytes(saved)
+ checks.append('committed authoring state survives process restart')
+ records.append(restarted.stats)
+
+ # Fixed small payload budget is an admission test, not a throughput workload.
+ with serving(binary, storage, budget=1024 * 1024, timeout=1200) as limited:
+ sock = socket.create_connection(('127.0.0.1', limited.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200
+ assert response.read(1) == large[:1]
+ status, headers, _ = rpc(limited, 'GET', 'large')
+ assert status == 503 and headers['X-Pure-Error'] == 'payload_budget'
+ # Leave the first receiver stalled until the absolute connection deadline.
+ time.sleep(1.4)
+ assert rpc(limited, 'GET', 'binary')[2] == b'new'
+ response.close()
+ sock.close()
+ checks.append('slow consumer retains its lease; budget rejects another; deadline releases it')
+
+ idle = [socket.create_connection(('127.0.0.1', limited.port), timeout=8) for _ in range(8)]
+ try:
+ for s in idle:
+ s.sendall(b'G')
+ for s in idle:
+ assert s.recv(1) == b''
+ finally:
+ for s in idle:
+ s.close()
+ assert rpc(limited, 'GET', 'binary')[0] == 200
+ checks.append('connection slots stay bounded and recover after header deadlines')
+ assert limited.stats['budget_rejections'] >= 1 and limited.stats['expired'] >= 9
+ records.append(limited.stats)
+ return {'kind': 'native-byte-path-correctness-not-performance', 'checks': checks,
+ 'server_runs': records, 'storage': server.ready['storage']}
+
+
+def rpc_bytes(path):
+ # CLI export is pretty JSON; wire export is compact JSON with the same model.
+ return json.dumps(json.loads(path.read_text()), ensure_ascii=False, separators=(',', ':')).encode()
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path, default=ROOT / 'build/pure-connections')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ binary = args.server.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-connections-check-') as temporary:
+ result = check(binary, Path(temporary))
+ result['binary_sha256'] = hashlib.sha256(binary.read_bytes()).hexdigest()
+ result['environment'] = {'platform': platform.platform(), 'machine': platform.machine(),
+ 'python': platform.python_version(), 'node': subprocess.check_output(['node', '--version'], text=True).strip()}
+ result['source_sha256'] = {str(path.relative_to(ROOT.parent.parent)): hashlib.sha256(path.read_bytes()).hexdigest()
+ for path in [*(ROOT / name for name in ('flow.c', 'flow.h', 'store.c', 'store.h', 'server.c', 'check.py', 'test-flow.c', 'Makefile')),
+ *(WORKBENCH / name for name in ('remote.mjs', 'cli.mjs', 'web/core.wasm', 'web/runtime.mjs',
+ 'web/compiler.mjs', 'web/project.mjs', 'examples/direct.pure'))]}
+ output = json.dumps(result, ensure_ascii=False, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/flow.c b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/flow.c
new file mode 100644
index 0000000..1070c70
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/flow.c
@@ -0,0 +1,41 @@
+#include "flow.h"
+#include <assert.h>
+
+void pure_transfer_abort(PureTransfer *t) {
+ if (!t->active) return;
+ PureRelease release = t->release;
+ void *owner = t->owner;
+ *t = (PureTransfer){0};
+ if (release) release(owner);
+}
+
+static void advance(PureTransfer *t) {
+ while (t->active && t->part < 2 && t->offset == t->spans[t->part].size) {
+ t->part++;
+ t->offset = 0;
+ }
+ if (t->active && t->part == 2) pure_transfer_abort(t);
+}
+
+void pure_transfer_init(PureTransfer *t, PureSpan header, PureSpan body,
+ void *owner, PureRelease release) {
+ assert(!t->active);
+ assert((!header.size || header.data) && (!body.size || body.data));
+ *t = (PureTransfer){.spans = {header, body}, .owner = owner,
+ .release = release, .active = true};
+ advance(t);
+}
+
+PureSpan pure_transfer_next(const PureTransfer *t, size_t limit) {
+ if (!t->active) return (PureSpan){0};
+ PureSpan span = t->spans[t->part];
+ size_t remaining = span.size - t->offset;
+ return (PureSpan){span.data + t->offset, remaining < limit ? remaining : limit};
+}
+
+bool pure_transfer_consume(PureTransfer *t, size_t bytes) {
+ if (!t->active || bytes > t->spans[t->part].size - t->offset) return false;
+ t->offset += bytes;
+ advance(t);
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/flow.h b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/flow.h
new file mode 100644
index 0000000..6e27c58
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/flow.h
@@ -0,0 +1,25 @@
+#ifndef PURE_FLOW_H
+#define PURE_FLOW_H
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef struct { const unsigned char *data; size_t size; } PureSpan;
+typedef void (*PureRelease)(void *owner);
+
+/* A borrowed body stays alive until every byte is consumed or the transfer is
+ * aborted. A successful send() consumes bytes; peer receipt is a separate fact.
+ * Single owner thread; callbacks must not reenter or reuse this transfer. */
+typedef struct {
+ PureSpan spans[2];
+ size_t part, offset;
+ void *owner;
+ PureRelease release;
+ bool active;
+} PureTransfer;
+
+void pure_transfer_init(PureTransfer *, PureSpan header, PureSpan body,
+ void *owner, PureRelease);
+PureSpan pure_transfer_next(const PureTransfer *, size_t limit);
+bool pure_transfer_consume(PureTransfer *, size_t bytes);
+void pure_transfer_abort(PureTransfer *);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/server.c b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/server.c
new file mode 100644
index 0000000..cea5af8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/server.c
@@ -0,0 +1,347 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+enum { SLOTS = 8, HEADER_LIMIT = 4096, CHUNK = 65536 };
+typedef enum { READING_HEADER, READING_BODY, WRITING } Phase;
+typedef struct Server Server;
+typedef struct {
+ int fd;
+ Phase phase;
+ uint64_t deadline;
+ char request[HEADER_LIMIT + 1], response[512], key[65];
+ size_t header_size, body_size, received, charged;
+ unsigned char *body;
+ bool put;
+ int64_t expected;
+ PureStoredView stored;
+ PureTransfer transfer;
+ Server *server;
+} Connection;
+struct Server {
+ const char *path;
+ size_t budget, retained, peak_retained, active, peak_active;
+ uint64_t accepted, commits, gets, conflicts, budget_rejections, expired;
+ uint64_t releases, prefix_copy_bytes, borrowed_output_bytes;
+ uint64_t timeout_ms;
+ int send_buffer;
+ Connection connections[SLOTS];
+};
+static volatile sig_atomic_t stopping;
+static void stop_server(int sig) { (void)sig; stopping = 1; }
+
+static uint64_t now_ms(void) {
+ struct timespec t;
+ if (clock_gettime(CLOCK_MONOTONIC, &t)) abort();
+ return (uint64_t)t.tv_sec * 1000 + (uint64_t)t.tv_nsec / 1000000;
+}
+
+static bool number(const char *text, uint64_t maximum, uint64_t *value) {
+ if (!*text) return false;
+ uint64_t n = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > maximum || n > (maximum - digit) / 10) return false;
+ n = n * 10 + digit;
+ }
+ *value = n;
+ return true;
+}
+
+static void release_payload(void *owner) {
+ Connection *c = owner;
+ bool owned = c->body || c->stored.mapped_size || c->charged;
+ pure_store_release(&c->stored);
+ free(c->body);
+ c->body = NULL;
+ assert(c->charged <= c->server->retained);
+ c->server->retained -= c->charged;
+ c->charged = 0;
+ if (owned) ++c->server->releases;
+}
+
+static void close_connection(Connection *c) {
+ if (c->fd < 0) return;
+ if (c->transfer.active) pure_transfer_abort(&c->transfer);
+ else if (c->body || c->stored.mapped_size || c->charged) release_payload(c);
+ close(c->fd);
+ --c->server->active;
+ *c = (Connection){.fd = -1};
+}
+
+static bool charge(Connection *c, size_t size) {
+ Server *s = c->server;
+ if (size > s->budget - s->retained) { ++s->budget_rejections; return false; }
+ s->retained += size;
+ c->charged += size;
+ if (s->retained > s->peak_retained) s->peak_retained = s->retained;
+ return true;
+}
+
+static void respond(Connection *c, int status, const char *reason, const char *error,
+ int64_t revision, PureSpan body) {
+ char tag[80] = "";
+ if (revision > 0) snprintf(tag, sizeof(tag), "ETag: \"%" PRId64 "\"\r\n", revision);
+ int length = snprintf(c->response, sizeof(c->response),
+ "HTTP/1.1 %d %s\r\nContent-Length: %zu\r\nConnection: close\r\n"
+ "Content-Type: application/octet-stream\r\nCache-Control: no-store\r\n"
+ "X-Pure-Error: %s\r\n%s\r\n", status, reason, body.size, error, tag);
+ assert(length > 0 && (size_t)length < sizeof(c->response));
+ c->phase = WRITING;
+ pure_transfer_init(&c->transfer,
+ (PureSpan){(const unsigned char *)c->response, (size_t)length}, body, c, release_payload);
+}
+
+static void fail(Connection *c, int status, const char *reason, const char *error) {
+ /* No outstanding backend access on the owner thread at this point. */
+ if (c->body || c->stored.mapped_size || c->charged) release_payload(c);
+ respond(c, status, reason, error, 0, (PureSpan){0});
+}
+
+static void run_request(Connection *c) {
+ PureResult result;
+ int64_t revision = 0;
+ if (c->put) {
+ result = pure_store_put(c->server->path, c->key, c->expected,
+ (PureSpan){c->body, c->body_size}, &revision);
+ /* The synchronous write no longer accesses this input on any result. */
+ release_payload(c);
+ if (result == PURE_OK) ++c->server->commits;
+ } else {
+ result = pure_store_get(c->server->path, c->key,
+ c->server->budget - c->server->retained, &c->stored);
+ if (result == PURE_OK) {
+ if (!charge(c, c->stored.body.size)) abort(); /* Same owner thread. */
+ revision = c->stored.revision;
+ ++c->server->gets;
+ c->server->borrowed_output_bytes += c->stored.body.size;
+ } else if (result == PURE_BUDGET) ++c->server->budget_rejections;
+ }
+ switch (result) {
+ case PURE_OK: respond(c, 200, "OK", "none", revision, c->stored.body); break;
+ case PURE_NOT_FOUND: fail(c, 404, "Not Found", "not_found"); break;
+ case PURE_CONFLICT:
+ ++c->server->conflicts;
+ respond(c, 412, "Precondition Failed", "conflict", revision, (PureSpan){0}); break;
+ case PURE_BUSY: fail(c, 503, "Service Unavailable", "store_busy"); break;
+ case PURE_BUDGET: fail(c, 503, "Service Unavailable", "payload_budget"); break;
+ case PURE_LIMIT: fail(c, 413, "Content Too Large", "limit"); break;
+ case PURE_UNCERTAIN: fail(c, 500, "Internal Server Error", "durability_unknown"); break;
+ default: fail(c, 500, "Internal Server Error", "storage"); break;
+ }
+}
+
+/* Deliberately bounded HTTP/1.1 subset: one GET/PUT, Content-Length, close.
+ * No transfer coding, pipelining, trailers, Expect, URL decoding, or proxying. */
+static bool parse_header(Connection *c, size_t end) {
+ for (size_t i = 0; i < end; ++i) {
+ unsigned char b = (unsigned char)c->request[i];
+ if ((b < 32 && b != '\r' && b != '\n' && b != '\t') || b == 127) return false;
+ }
+ char *line = c->request, *next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *path = strchr(line, ' ');
+ if (!path) return false;
+ *path++ = 0;
+ if (strcmp(line, "PUT") == 0) c->put = true;
+ else if (strcmp(line, "GET") != 0) return false;
+ char *version = strchr(path, ' ');
+ if (!version) return false;
+ *version++ = 0;
+ if (strcmp(version, "HTTP/1.1") || strncmp(path, "/objects/", 9)) return false;
+ const char *key = path + 9;
+ size_t key_size = strlen(key);
+ if (!key_size || key_size > 64) return false;
+ for (size_t i = 0; i < key_size; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ memcpy(c->key, key, key_size + 1);
+ bool length_seen = false, condition_seen = false, host_seen = false;
+ line = next + 2;
+ while (*line != '\r') {
+ next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *value = strchr(line, ':');
+ if (!value || value == line) return false;
+ *value++ = 0;
+ for (char *p = line; *p; ++p)
+ if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') || *p == '-')) return false;
+ while (*value == ' ' || *value == '\t') ++value;
+ char *tail = value + strlen(value);
+ while (tail > value && (tail[-1] == ' ' || tail[-1] == '\t')) *--tail = 0;
+ if (strchr(value, '\r') || strchr(value, '\n')) return false;
+ uint64_t n;
+ if (!strcasecmp(line, "Content-Length")) {
+ if (length_seen || !number(value, SIZE_MAX, &n)) return false;
+ length_seen = true;
+ c->body_size = (size_t)n;
+ } else if (!strcasecmp(line, "Host")) {
+ if (host_seen || !*value) return false;
+ host_seen = true;
+ } else if (!strcasecmp(line, "If-Match")) {
+ if (condition_seen || tail - value < 3 || *value != '"' || tail[-1] != '"') return false;
+ tail[-1] = 0;
+ if (!number(value + 1, INT64_MAX, &n) || !n) return false;
+ c->expected = (int64_t)n;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "If-None-Match")) {
+ if (condition_seen || strcmp(value, "*")) return false;
+ c->expected = 0;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "Transfer-Encoding") || !strcasecmp(line, "Expect")) return false;
+ line = next + 2;
+ }
+ return host_seen && (c->put ? length_seen && condition_seen : !condition_seen && c->body_size == 0);
+}
+
+static void read_connection(Connection *c) {
+ if (c->phase == READING_HEADER) {
+ ssize_t n = recv(c->fd, c->request + c->header_size, HEADER_LIMIT - c->header_size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->header_size += (size_t)n;
+ c->request[c->header_size] = 0;
+ /* Scan by byte count, so embedded NUL cannot hide a terminator. */
+ size_t end = 0;
+ for (size_t i = 3; i < c->header_size; ++i)
+ if (!memcmp(c->request + i - 3, "\r\n\r\n", 4)) { end = i + 1; break; }
+ if (!end) {
+ if (c->header_size == HEADER_LIMIT) fail(c, 431, "Request Header Fields Too Large", "headers");
+ return;
+ }
+ size_t prefix = c->header_size - end;
+ if (!parse_header(c, end)) { fail(c, 400, "Bad Request", "request"); return; }
+ if (c->body_size > PURE_OBJECT_LIMIT) { fail(c, 413, "Content Too Large", "limit"); return; }
+ if (prefix > c->body_size) { fail(c, 400, "Bad Request", "extra_body"); return; }
+ if (!c->put) { run_request(c); return; }
+ if (!charge(c, c->body_size)) { fail(c, 503, "Service Unavailable", "payload_budget"); return; }
+ c->body = malloc(c->body_size ? c->body_size : 1);
+ if (!c->body) { fail(c, 503, "Service Unavailable", "allocation"); return; }
+ if (prefix) memcpy(c->body, c->request + end, prefix);
+ c->server->prefix_copy_bytes += prefix;
+ c->received = prefix;
+ c->phase = READING_BODY;
+ if (c->received == c->body_size) run_request(c);
+ } else {
+ size_t remaining = c->body_size - c->received;
+ ssize_t n = recv(c->fd, c->body + c->received, remaining < CHUNK ? remaining : CHUNK, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->received += (size_t)n;
+ if (c->received == c->body_size) run_request(c);
+ }
+}
+
+static void write_connection(Connection *c) {
+ PureSpan span = pure_transfer_next(&c->transfer, CHUNK);
+ ssize_t n = send(c->fd, span.data, span.size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ if (!pure_transfer_consume(&c->transfer, (size_t)n)) abort();
+ if (!c->transfer.active) close_connection(c);
+}
+
+static bool nonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
+}
+
+int main(int argc, char **argv) {
+ Server server = {.budget = 4u * 1024u * 1024u, .timeout_ms = 10000};
+ unsigned port = 8767;
+ for (int i = 1; i < argc; i += 2) {
+ if (i + 1 == argc) goto usage;
+ uint64_t value;
+ if (!strcmp(argv[i], "--store")) server.path = argv[i + 1];
+ else if (!strcmp(argv[i], "--port") && number(argv[i + 1], 65535, &value)) port = (unsigned)value;
+ else if (!strcmp(argv[i], "--budget") && number(argv[i + 1], SIZE_MAX, &value) && value) server.budget = (size_t)value;
+ else if (!strcmp(argv[i], "--timeout-ms") && number(argv[i + 1], 3600000, &value) && value) server.timeout_ms = value;
+ else if (!strcmp(argv[i], "--send-buffer") && number(argv[i + 1], INT32_MAX, &value)) server.send_buffer = (int)value;
+ else goto usage;
+ }
+ if (!server.path) goto usage;
+ if (pure_store_init(server.path) != PURE_OK) { fputs("Cannot initialize byte store directory\n", stderr); return 1; }
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, stop_server);
+ signal(SIGTERM, stop_server);
+ int listener = socket(AF_INET, SOCK_STREAM, 0);
+ if (listener < 0) { perror("socket"); return 1; }
+ int one = 1;
+ setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ struct sockaddr_in address = {.sin_family = AF_INET, .sin_port = htons((uint16_t)port),
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ if (bind(listener, (struct sockaddr *)&address, sizeof(address)) || listen(listener, SLOTS) || !nonblocking(listener)) {
+ perror("listen"); close(listener); return 1;
+ }
+ socklen_t address_size = sizeof(address);
+ if (getsockname(listener, (struct sockaddr *)&address, &address_size)) { close(listener); return 1; }
+ for (size_t i = 0; i < SLOTS; ++i) server.connections[i].fd = -1;
+ printf("{\"port\":%u,\"storage\":\"immutable-byte-extents-v1\"}\n", ntohs(address.sin_port));
+ fflush(stdout);
+ while (!stopping) {
+ struct pollfd polls[SLOTS + 1] = {{.fd = server.active < SLOTS ? listener : -1, .events = POLLIN}};
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ polls[i + 1] = (struct pollfd){.fd = c->fd, .events = c->phase == WRITING ? POLLOUT : POLLIN};
+ }
+ int ready = poll(polls, SLOTS + 1, 50);
+ if (ready < 0 && errno != EINTR) { perror("poll"); stopping = 1; }
+ uint64_t now = now_ms();
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ if (c->fd < 0) continue;
+ if (now >= c->deadline) { ++server.expired; close_connection(c); continue; }
+ short events = polls[i + 1].revents;
+ if (events & (POLLERR | POLLNVAL)) { close_connection(c); continue; }
+ if (events & (POLLIN | POLLOUT | POLLHUP)) {
+ if (c->phase == WRITING) write_connection(c); else read_connection(c);
+ }
+ }
+ if (!stopping && (polls[0].revents & POLLIN)) {
+ int fd = accept(listener, NULL, NULL);
+ if (fd < 0) continue;
+ if (!nonblocking(fd)) { close(fd); continue; }
+ if (server.send_buffer) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &server.send_buffer, sizeof(server.send_buffer));
+ for (size_t i = 0; i < SLOTS; ++i) if (server.connections[i].fd < 0) {
+ server.connections[i] = (Connection){.fd = fd, .server = &server, .deadline = now_ms() + server.timeout_ms};
+ ++server.active;
+ ++server.accepted;
+ if (server.active > server.peak_active) server.peak_active = server.active;
+ break;
+ }
+ }
+ }
+ close(listener);
+ for (size_t i = 0; i < SLOTS; ++i) close_connection(&server.connections[i]);
+ fprintf(stderr, "{\"active\":%zu,\"retained_payload_bytes\":%zu,\"peak_retained_payload_bytes\":%zu,"
+ "\"payload_budget\":%zu,\"peak_connections\":%zu,\"accepted\":%" PRIu64 ",\"commits\":%" PRIu64 ","
+ "\"gets\":%" PRIu64 ",\"conflicts\":%" PRIu64 ",\"budget_rejections\":%" PRIu64 ","
+ "\"expired\":%" PRIu64 ",\"releases\":%" PRIu64 ",\"ingress_prefix_copy_bytes\":%" PRIu64 ","
+ "\"borrowed_output_bytes\":%" PRIu64 ",\"server_structure_bytes\":%zu}\n",
+ server.active, server.retained, server.peak_retained, server.budget, server.peak_active,
+ server.accepted, server.commits, server.gets, server.conflicts, server.budget_rejections,
+ server.expired, server.releases, server.prefix_copy_bytes, server.borrowed_output_bytes, sizeof(server));
+ return 0;
+usage:
+ fputs("pure-connections --store DIRECTORY [--port 8767] [--budget BYTES] [--timeout-ms 10000] [--send-buffer BYTES]\n", stderr);
+ return 2;
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/store.c b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/store.c
new file mode 100644
index 0000000..d0111d0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/store.c
@@ -0,0 +1,225 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Immutable extent envelope: marker, little-endian u64 revision and payload
+ * length, then unchanged caller bytes. Single-threaded control API; cooperating
+ * processes serialize publication using .writer.lock. */
+enum { HEADER_BYTES = 24 };
+static const unsigned char magic[8] = {'P','U','R','E','B','0','0','1'};
+static uint64_t temporary_sequence;
+
+static bool fault(PureStoreStage stage) {
+#ifdef PURE_STORE_TEST
+ if (pure_store_test_fault(stage)) { errno = EIO; return true; }
+#else
+ (void)stage;
+#endif
+ return false;
+}
+
+static bool file_name(const char *key, char name[72]) {
+ if (!key) return false;
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ snprintf(name, 72, "obj-%s", key);
+ return true;
+}
+
+static uint64_t decode64(const unsigned char *bytes) {
+ uint64_t value = 0;
+ for (unsigned i = 0; i < 8; ++i) value |= (uint64_t)bytes[i] << (8 * i);
+ return value;
+}
+
+static void encode64(unsigned char *bytes, uint64_t value) {
+ for (unsigned i = 0; i < 8; ++i) bytes[i] = (unsigned char)(value >> (8 * i));
+}
+
+static bool sync_fd(int fd) {
+ int rc;
+ do { rc = fsync(fd); } while (rc && errno == EINTR);
+ return rc == 0;
+}
+
+static bool write_bytes(int fd, const unsigned char *bytes, size_t length) {
+ while (length) {
+ ssize_t n = write(fd, bytes, length);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ bytes += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static bool read_header(int fd, int64_t *revision, size_t *length) {
+ struct stat info;
+ if (fstat(fd, &info) || !S_ISREG(info.st_mode)) return false;
+ unsigned char header[HEADER_BYTES];
+ size_t used = 0;
+ while (used < sizeof(header)) {
+ ssize_t n = pread(fd, header + used, sizeof(header) - used, (off_t)used);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ used += (size_t)n;
+ }
+ uint64_t version = decode64(header + 8), size = decode64(header + 16);
+ if (memcmp(header, magic, sizeof(magic)) || !version || version > INT64_MAX ||
+ size > PURE_OBJECT_LIMIT || info.st_size != (off_t)(HEADER_BYTES + size)) return false;
+ *revision = (int64_t)version;
+ *length = (size_t)size;
+ return true;
+}
+
+PureResult pure_store_init(const char *path) {
+ if (!path || !*path) return PURE_STORE_ERROR;
+ bool created = mkdir(path, 0700) == 0;
+ if (!created && errno != EEXIST) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR; /* Never reinterpret an old DB file. */
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600);
+ struct stat info;
+ bool ok = lock >= 0 && fstat(lock, &info) == 0 && S_ISREG(info.st_mode) && sync_fd(lock);
+ if (lock >= 0) close(lock);
+ if (ok) ok = sync_fd(directory);
+ close(directory);
+ if (!ok) return PURE_STORE_ERROR;
+ if (created) {
+ char *parent = strdup(path);
+ if (!parent) return PURE_STORE_ERROR;
+ size_t length = strlen(parent);
+ while (length > 1 && parent[length - 1] == '/') parent[--length] = 0;
+ char *slash = strrchr(parent, '/');
+ if (!slash) strcpy(parent, ".");
+ else if (slash == parent) parent[1] = 0;
+ else *slash = 0;
+ int fd = open(parent, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ free(parent);
+ ok = fd >= 0 && sync_fd(fd);
+ if (fd >= 0) close(fd);
+ }
+ return ok ? PURE_OK : PURE_STORE_ERROR;
+}
+
+void pure_store_release(PureStoredView *view) {
+ if (view->mapped_size) munmap(view->mapping, view->mapped_size);
+ *view = (PureStoredView){0};
+}
+
+static PureResult view_range(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t available, PureStoredView *out) {
+ *out = (PureStoredView){0};
+ char name[72];
+ if (!file_name(key, name)) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ int cause = errno;
+ close(directory);
+ if (fd < 0) return cause == ENOENT ? PURE_NOT_FOUND : PURE_STORE_ERROR;
+ int64_t revision;
+ size_t size;
+ PureResult result = PURE_STORE_ERROR;
+ if (!read_header(fd, &revision, &size)) goto finish;
+ if (whole) { offset = 0; length = size; }
+ if (offset > size || length > size - offset) { result = PURE_LIMIT; goto finish; }
+ if (length > available) { result = PURE_BUDGET; goto finish; }
+ if (length) {
+ long page = sysconf(_SC_PAGESIZE);
+ if (page <= 0) goto finish;
+ size_t start = HEADER_BYTES + offset;
+ size_t aligned = start - start % (size_t)page;
+ size_t prefix = start - aligned;
+ size_t mapped_size = prefix + length;
+ void *mapping = mmap(NULL, mapped_size, PROT_READ, MAP_PRIVATE, fd, (off_t)aligned);
+ if (mapping == MAP_FAILED) goto finish;
+ out->mapping = mapping;
+ out->mapped_size = mapped_size;
+ out->body = (PureSpan){(const unsigned char *)mapping + prefix, length};
+ }
+ out->revision = revision;
+ out->object_size = size;
+ result = PURE_OK;
+finish:
+ close(fd); /* The mapping retains this immutable file version after rename. */
+ return result;
+}
+
+PureResult pure_store_get(const char *path, const char *key, size_t available, PureStoredView *out) {
+ return view_range(path, key, 0, 0, true, available, out);
+}
+
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out) {
+ return view_range(path, key, offset, length, false, available, out);
+}
+
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ *revision = 0;
+ char name[72], temporary[96] = "";
+ if (!file_name(key, name) || (body.size && !body.data)) return PURE_STORE_ERROR;
+ if (body.size > PURE_OBJECT_LIMIT || expected < 0) return PURE_LIMIT;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_NOFOLLOW | O_CLOEXEC);
+ int fd = -1;
+ PureResult result = PURE_STORE_ERROR;
+ struct stat info;
+ if (lock < 0 || fstat(lock, &info) || !S_ISREG(info.st_mode)) goto finish;
+ struct flock hold = {.l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0};
+ if (fcntl(lock, F_SETLK, &hold)) {
+ if (errno == EACCES || errno == EAGAIN) result = PURE_BUSY;
+ goto finish;
+ }
+ fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (fd >= 0) {
+ size_t size;
+ if (!read_header(fd, revision, &size)) goto finish;
+ close(fd);
+ fd = -1;
+ } else if (errno != ENOENT) goto finish;
+ if (*revision != expected) { result = PURE_CONFLICT; goto finish; }
+ if (*revision == INT64_MAX) { result = PURE_LIMIT; goto finish; }
+ for (unsigned attempt = 0; attempt < 64; ++attempt) {
+ if (temporary_sequence == UINT64_MAX) goto finish;
+ snprintf(temporary, sizeof(temporary), ".pending-%ld-%" PRIu64, (long)getpid(), ++temporary_sequence);
+ fd = openat(directory, temporary, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
+ if (fd >= 0) break;
+ temporary[0] = 0; /* Never remove an existing file on a name collision. */
+ if (errno != EEXIST) goto finish;
+ }
+ if (fd < 0) goto finish;
+ unsigned char header[HEADER_BYTES];
+ memcpy(header, magic, sizeof(magic));
+ encode64(header + 8, (uint64_t)*revision + 1);
+ encode64(header + 16, body.size);
+ if (!write_bytes(fd, header, sizeof(header)) || fault(PURE_AFTER_HEADER) ||
+ !write_bytes(fd, body.data, body.size) || fault(PURE_BEFORE_FILE_SYNC) || !sync_fd(fd)) goto finish;
+ int close_result = close(fd);
+ fd = -1;
+ if (close_result || fault(PURE_BEFORE_RENAME) || renameat(directory, temporary, directory, name)) goto finish;
+ temporary[0] = 0; /* Published: a later sync failure does not roll it back. */
+ ++*revision;
+ result = fault(PURE_BEFORE_DIR_SYNC) || !sync_fd(directory) ? PURE_UNCERTAIN : PURE_OK;
+finish:
+ if (fd >= 0) close(fd);
+ if (*temporary) unlinkat(directory, temporary, 0);
+ if (lock >= 0) close(lock);
+ close(directory);
+ return result;
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/store.h b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/store.h
new file mode 100644
index 0000000..d9bcc1c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/store.h
@@ -0,0 +1,34 @@
+#ifndef PURE_STORE_H
+#define PURE_STORE_H
+#include "flow.h"
+#include <stdint.h>
+
+#define PURE_OBJECT_LIMIT ((2u * 6u + 32u) * 32768u + 8192u)
+typedef enum {
+ PURE_OK, PURE_NOT_FOUND, PURE_CONFLICT, PURE_BUSY, PURE_BUDGET,
+ PURE_LIMIT, PURE_STORE_ERROR, PURE_UNCERTAIN
+} PureResult;
+typedef struct {
+ void *mapping;
+ size_t mapped_size, object_size;
+ PureSpan body;
+ int64_t revision;
+} PureStoredView;
+
+PureResult pure_store_init(const char *path);
+PureResult pure_store_get(const char *path, const char *key, size_t available,
+ PureStoredView *out);
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out);
+void pure_store_release(PureStoredView *);
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision);
+
+/* Fault hooks exist only in the separately built unit-test binary. */
+typedef enum {
+ PURE_AFTER_HEADER, PURE_BEFORE_FILE_SYNC, PURE_BEFORE_RENAME, PURE_BEFORE_DIR_SYNC
+} PureStoreStage;
+#ifdef PURE_STORE_TEST
+int pure_store_test_fault(PureStoreStage stage);
+#endif
+#endif
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/test-flow.c b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/test-flow.c
new file mode 100644
index 0000000..5ff028d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/connections/test-flow.c
@@ -0,0 +1,183 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static int failed_stage = -1;
+static bool crash_at_stage;
+int pure_store_test_fault(PureStoreStage stage) {
+ if ((int)stage != failed_stage) return 0;
+ if (crash_at_stage) _exit(77);
+ return 1;
+}
+typedef struct { unsigned char *bytes; unsigned releases; } Owner;
+static void release(void *raw) {
+ Owner *owner = raw;
+ free(owner->bytes);
+ owner->bytes = NULL;
+ ++owner->releases;
+}
+
+static void transfers(void) {
+ Owner owner = {.bytes = malloc(5)};
+ CHECK(owner.bytes);
+ memcpy(owner.bytes, "a\0bcd", 5);
+ PureTransfer transfer = {0};
+ pure_transfer_init(&transfer, (PureSpan){(const unsigned char *)"head", 4},
+ (PureSpan){owner.bytes, 5}, &owner, release);
+ CHECK(!pure_transfer_consume(&transfer, 5));
+ CHECK(transfer.active && !owner.releases);
+ CHECK(pure_transfer_consume(&transfer, 0));
+ unsigned char received[9];
+ size_t used = 0;
+ while (transfer.active) {
+ PureSpan span = pure_transfer_next(&transfer, 2);
+ CHECK(span.size && span.size <= 2);
+ memcpy(received + used, span.data, span.size);
+ used += span.size;
+ CHECK(pure_transfer_consume(&transfer, span.size));
+ CHECK((used == 9) == (owner.releases == 1));
+ }
+ CHECK(used == 9 && !memcmp(received, "heada\0bcd", 9));
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 1 && !pure_transfer_consume(&transfer, 0));
+ owner.bytes = malloc(3);
+ CHECK(owner.bytes);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){owner.bytes, 3}, &owner, release);
+ CHECK(pure_transfer_consume(&transfer, 1));
+ pure_transfer_abort(&transfer);
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 2 && !transfer.active);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){0}, &owner, release);
+ CHECK(owner.releases == 3 && !transfer.active);
+}
+
+static void storage(const char *path) {
+ CHECK(pure_store_init(path) == PURE_OK);
+ PureStoredView first, second;
+ CHECK(pure_store_get(path, "missing", 100, &first) == PURE_NOT_FOUND);
+ CHECK(!first.mapping && !first.mapped_size);
+ static const unsigned char original[] = {0, 1, 2, 255, 17};
+ static const unsigned char updated[] = {9, 8, 7};
+ int64_t revision;
+ CHECK(pure_store_put(path, "work", 0, (PureSpan){original, sizeof(original)}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ CHECK(pure_store_get(path, "work", sizeof(original) - 1, &first) == PURE_BUDGET);
+ CHECK(!first.mapping && !first.mapped_size);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 3, &first) == PURE_OK);
+ CHECK(first.object_size == sizeof(original) && first.body.size == 3 && !memcmp(first.body.data, original + 1, 3));
+ pure_store_release(&first);
+ CHECK(pure_store_get_range(path, "work", SIZE_MAX, 1, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, SIZE_MAX, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 2, &first) == PURE_BUDGET);
+ CHECK(pure_store_get_range(path, "work", sizeof(original), 0, 0, &first) == PURE_OK);
+ CHECK(!first.mapped_size && !first.body.size);
+ pure_store_release(&first);
+ CHECK(pure_store_get(path, "work", sizeof(original), &first) == PURE_OK);
+ CHECK(first.body.size == sizeof(original) && first.revision == 1);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 2);
+ CHECK(!memcmp(first.body.data, original, sizeof(original)));
+ CHECK(pure_store_get(path, "work", 100, &second) == PURE_OK);
+ CHECK(second.revision == 2 && second.body.size == sizeof(updated));
+ CHECK(!memcmp(second.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ pure_store_release(&first);
+ pure_store_release(&second);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){original, sizeof(original)}, &revision) == PURE_CONFLICT);
+ CHECK(revision == 2);
+
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 2 && !memcmp(first.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == 3);
+ failed_stage = -1;
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_CONFLICT);
+
+ /* A crashed unpublished writer leaves only a private file. A new publisher
+ * must still use the previous committed version, never an incomplete body. */
+ pid_t child = fork();
+ CHECK(child >= 0);
+ if (!child) {
+ failed_stage = PURE_AFTER_HEADER;
+ crash_at_stage = true;
+ pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision);
+ _exit(78);
+ }
+ int status;
+ CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 77);
+ CHECK(pure_store_init(path) == PURE_OK);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 4);
+
+ char file[320];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ CHECK(fd >= 0);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_put(path, "work", INT64_MAX, (PureSpan){original, sizeof(original)}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_put(path, "empty", 0, (PureSpan){0}, &revision) == PURE_OK);
+ CHECK(pure_store_get(path, "empty", 0, &first) == PURE_OK && first.body.size == 0);
+ pure_store_release(&first);
+
+ /* Range mapping crosses page boundaries without copying a whole object. */
+ long page = sysconf(_SC_PAGESIZE);
+ CHECK(page >= 128 && (size_t)page <= PURE_OBJECT_LIMIT / 3);
+ size_t size = (size_t)page * 3, offset = (size_t)page + 13, length = (size_t)page + 105;
+ unsigned char *bytes = malloc(size);
+ CHECK(bytes);
+ for (size_t i = 0; i < size; ++i) bytes[i] = (unsigned char)((i * 17u) ^ (i >> 8) ^ (i >> 16));
+ CHECK(pure_store_put(path, "range", 0, (PureSpan){bytes, size}, &revision) == PURE_OK);
+ CHECK(pure_store_get_range(path, "range", offset, length, length, &first) == PURE_OK);
+ CHECK(first.body.size == length && !memcmp(first.body.data, bytes + offset, length));
+ pure_store_release(&first);
+ free(bytes);
+ snprintf(file, sizeof(file), "%s/obj-broken", path);
+ fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0600);
+ CHECK(fd >= 0 && write(fd, "incomplete", 10) == 10 && close(fd) == 0);
+ CHECK(pure_store_get(path, "broken", 100, &first) == PURE_STORE_ERROR && !first.mapped_size);
+ CHECK(pure_store_put(path, "broken", 0, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_init(file) == PURE_STORE_ERROR);
+ struct stat info;
+ CHECK(stat(file, &info) == 0 && info.st_size == 10);
+}
+
+int main(void) {
+ transfers();
+ char directory[] = "/tmp/pure-connection-unit-XXXXXX";
+ CHECK(mkdtemp(directory));
+ char path[256];
+ snprintf(path, sizeof(path), "%s/store", directory);
+ storage(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ CHECK(rmdir(directory) == 0);
+ puts("{\"transfer\":\"partial-consumption-and-single-release\","
+ "\"storage\":\"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty\"}");
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/cli.mjs b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/cli.mjs
new file mode 100644
index 0000000..b67f4d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/cli.mjs
@@ -0,0 +1,127 @@
+#!/usr/bin/env node
+import { readFile, writeFile } from 'node:fs/promises';
+import { createInterface } from 'node:readline';
+import { createRuntime } from './web/runtime.mjs';
+import { parseProject } from './web/project.mjs';
+import { remoteTarget, pushProject, pullProject } from './remote.mjs';
+
+const help = `Pure authoring workbench · 같은 정의와 Zig 실행기
+ load PATH .pure 파일을 적용 (같은 이름의 상태 보존)
+ down NAME 정의한 입력 누르기
+ up NAME 정의한 입력 놓기
+ point NAME PHASE X Y 좌표 입력 (down / move / up / cancel)
+ point-target NAME VIEW PHASE X Y 그룹의 대상에 좌표 입력
+ change NAME VALUE 숫자 입력 전달
+ frame [1..600] 시간 진행, 1프레임 = 1/60초
+ show 상태와 도형 출력
+ limits C H W 표시 캐시(0..32)·변경 기록(0..8)·작업량(0..4294967295) 설정
+ forget [PART] 표시 기록 삭제: all, values, history (상태는 유지)
+ costs 마지막 표시 계산의 작업량·명령 수·캐시 적중 출력
+ reset 현재 정의의 초기 상태로
+ save PATH 적용한 정의를 저장
+ save-project PATH 적용 코드와 현재 배치를 JSON으로 저장
+ restore PATH 저장한 배치를 복원 (초안이 있으면 파일에 보존)
+ connect URL KEY 로컬 네이티브 저장 서버의 작업물에 연결
+ push [REVISION] 현재 배치를 저장 (첫 생성은 push 0, 충돌 시 기존 값 유지)
+ pull 원격 배치를 검증·복원하고 revision 기억
+ help / quit
+브라우저와 별도 인스턴스입니다. 임의 JavaScript는 실행하지 않습니다.`;
+
+async function main() {
+ const args = process.argv.slice(2);
+ if (args.includes('--help')) { console.log(help); return; }
+ if (args.length > 1) throw new Error('사용법: node cli.mjs [project.pure]');
+ const runtime = await createRuntime(await readFile(new URL('./web/core.wasm', import.meta.url)));
+ let savedDraft = null;
+ let remote = null, remoteRevision = null;
+ async function loadFile(path, restoreOnly = false) {
+ const content = await readFile(path, 'utf8');
+ if (restoreOnly || path.toLowerCase().endsWith('.json')) {
+ const project = parseProject(content);
+ if (project.version === 2) {
+ savedDraft = runtime.restoreDocument(project).draft;
+ return;
+ }
+ if (restoreOnly) throw new Error('현재 배치가 포함된 version 2 파일이 필요합니다.');
+ runtime.apply(project.source);
+ } else runtime.apply(content);
+ savedDraft = null;
+ }
+ if (args[0]) await loadFile(args[0]); else runtime.apply('');
+ const terminal = createInterface({ input: process.stdin, output: process.stdout, terminal: Boolean(process.stdin.isTTY) });
+ if (process.stdin.isTTY) console.log(help);
+ terminal.setPrompt('pure> ');
+ if (process.stdin.isTTY) terminal.prompt();
+ for await (const line of terminal) {
+ try {
+ const match = /^(\S+)(?:\s+(.+))?$/.exec(line.trim());
+ const name = match?.[1] || 'show';
+ const arg = match?.[2];
+ if (name === 'quit') { terminal.close(); break; }
+ if (name === 'help') console.log(help);
+ else if (name === 'costs' && !arg) console.log(JSON.stringify({ evaluation: runtime.evaluationStats() }));
+ else {
+ if (name === 'load' && arg) await loadFile(arg);
+ else if (name === 'restore' && arg) await loadFile(arg, true);
+ else if (name === 'connect' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('connect URL KEY 형식을 사용하세요.');
+ remote = remoteTarget(parts[0], parts[1]);
+ remoteRevision = null;
+ console.log(JSON.stringify({ remote: remote.href }));
+ } else if (name === 'push') {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const expected = arg ?? remoteRevision;
+ if (expected === null) throw new Error('먼저 pull로 버전을 읽거나 push 0으로 새 작업물을 만드세요.');
+ remoteRevision = await pushProject(remote, expected, runtime.exportDocument(savedDraft ?? undefined));
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, stored: true }));
+ } else if (name === 'pull' && !arg) {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const loaded = await pullProject(remote);
+ savedDraft = runtime.restoreDocument(loaded.project).draft;
+ remoteRevision = loaded.revision;
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, restored: true }));
+ }
+ else if (name === 'save-project' && arg) await writeFile(arg, JSON.stringify(runtime.exportDocument(savedDraft ?? undefined), null, 2) + '\n', {flag:'wx'});
+ else if (name === 'save' && arg) await writeFile(arg, runtime.exportProject().source, { flag: 'wx' });
+ else if (name === 'down' && arg) runtime.down(arg, 'terminal');
+ else if (name === 'up' && arg) runtime.up(arg, 'terminal');
+ else if (name === 'point' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 4) throw new Error('point NAME PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[1], Number(parts[2]), Number(parts[3]), 'terminal');
+ } else if (name === 'point-target' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 5) throw new Error('point-target NAME VIEW PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[2], Number(parts[3]), Number(parts[4]), 'terminal', parts[1]);
+ } else if (name === 'change' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('change NAME VALUE 형식을 사용하세요.');
+ runtime.change(parts[0], Number(parts[1]), 'terminal');
+ } else if (name === 'frame') {
+ if (arg !== undefined && !/^\d+$/.test(arg)) throw new Error('frame 1..600 정수를 입력하세요.');
+ const count = arg === undefined ? 1 : Number(arg);
+ if (count < 1 || count > 600) throw new Error('frame 1..600 정수를 입력하세요.');
+ runtime.frame(count);
+ } else if (name === 'reset' && !arg) runtime.reset();
+ else if (name === 'limits' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 3 || parts.some(part => !/^\d+$/.test(part)))
+ throw new Error('limits C H W 정수 세 개를 입력하세요.');
+ const [cacheEntries, historyEntries, workLimit] = parts.map(Number);
+ runtime.configureEvaluation({ cacheEntries, historyEntries, workLimit });
+ } else if (name === 'forget') runtime.forgetEvaluation(arg || 'all');
+ else if (name !== 'show' || arg) throw new Error('명령 형식을 확인하세요. help로 안내를 볼 수 있습니다.');
+ const result = runtime.snapshot();
+ console.log(JSON.stringify(result));
+ if (result.lastError && !process.stdin.isTTY) process.exitCode = 1;
+ }
+ } catch (error) {
+ console.error(`${error.line ? `${error.line}:${error.column || 1} ` : ''}${error.message}`);
+ if (!process.stdin.isTTY) process.exitCode = 1;
+ }
+ if (process.stdin.isTTY) terminal.prompt();
+ }
+}
+
+main().catch((error) => { console.error(error.message); process.exitCode = 1; });
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/examples/direct.pure b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/examples/direct.pure
new file mode 100644
index 0000000..b29721c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/examples/direct.pure
@@ -0,0 +1,47 @@
+# 도형을 잡은 위치를 유지해 이동합니다. 취소하면 잡기 전 위치로 돌아갑니다.
+state x = 80
+state y = 160
+state grab_x = 0
+state grab_y = 0
+state start_x = 80
+state start_y = 160
+state dragging = 0
+
+input drag = pointer(tile)
+input left = ArrowLeft
+input right = ArrowRight
+
+box left_area(20, 100, 280, 220, "#233a31")
+box right_area(340, 100, 280, 220, "#343b25")
+box tile(x, y, 56, 44, "#c9f08b")
+text horizontal(30, 45, x, "x: ")
+text vertical(180, 45, y, "y: ")
+text region(350, 70, x >= 320, "오른쪽 영역: ")
+text active(30, 75, dragging, "잡고 있음: ")
+
+on drag.down {
+ start_x = x
+ start_y = y
+ grab_x = event_x - x
+ grab_y = event_y - y
+ dragging = 1
+}
+on drag.move {
+ x = clamp(event_x - grab_x, 20, 564)
+ y = clamp(event_y - grab_y, 100, 276)
+}
+on drag.up {
+ # 놓기는 마지막으로 표시한 위치를 확정합니다.
+ dragging = 0
+}
+on drag.cancel {
+ x = start_x
+ y = start_y
+ dragging = 0
+}
+on left.down {
+ if dragging == 0 { x = max(20, x - 10) }
+}
+on right.down {
+ if dragging == 0 { x = min(564, x + 10) }
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/remote.mjs b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/remote.mjs
new file mode 100644
index 0000000..6ee6a59
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/remote.mjs
@@ -0,0 +1,89 @@
+import http from 'node:http';
+import { MAX_PROJECT_BYTES, parseProject } from './web/project.mjs';
+
+const maxRevision = 9223372036854775807n;
+function revisionText(value, allowZero = false) {
+ if (typeof value !== 'string' || !/^(0|[1-9]\d*)$/.test(value) ||
+ value.length > 19 || BigInt(value) > maxRevision || (!allowZero && value === '0'))
+ throw new Error('revision은 범위 안의 정수 문자열이어야 합니다.');
+ return value;
+}
+
+export function remoteTarget(base, key) {
+ const url = new URL(base);
+ if (url.protocol !== 'http:' || !['127.0.0.1', 'localhost'].includes(url.hostname) ||
+ url.username || url.password || url.pathname !== '/' || url.search || url.hash)
+ throw new Error('현재 연결 호스트는 로컬 http://127.0.0.1:PORT 형식을 사용합니다.');
+ if (!/^[A-Za-z0-9_-]{1,64}$/.test(key)) throw new Error('작업물 이름은 영문·숫자·_·- 1~64자입니다.');
+ url.hostname = '127.0.0.1';
+ url.pathname = `/objects/${key}`;
+ return url;
+}
+
+function request(url, method, body, headers = {}) {
+ return new Promise((resolve, reject) => {
+ let done = false;
+ const finish = (error, value) => {
+ if (done) return;
+ done = true;
+ clearTimeout(deadline);
+ if (error) reject(error); else resolve(value);
+ };
+ const req = http.request(url, { method, agent: false, headers: { ...headers,
+ 'Content-Length': body?.byteLength ?? 0, Connection: 'close' } }, (res) => {
+ const chunks = [];
+ let size = 0;
+ res.on('data', (chunk) => {
+ size += chunk.length;
+ if (size > MAX_PROJECT_BYTES) {
+ const error = new Error('서버 작업물이 허용 크기를 넘었습니다.');
+ finish(error);
+ res.destroy(error);
+ req.destroy(error);
+ } else chunks.push(chunk);
+ });
+ res.on('error', (error) => finish(error));
+ res.on('aborted', () => finish(new Error('응답이 완료되기 전에 연결이 끊겼습니다.')));
+ res.on('end', () => {
+ if (res.statusCode !== 200) {
+ const error = new Error(`원격 작업 실패: ${res.statusCode} ${res.headers['x-pure-error'] ?? ''}`.trim());
+ error.status = res.statusCode;
+ error.etag = res.headers.etag;
+ finish(error);
+ return;
+ }
+ try {
+ const match = /^"([1-9]\d*)"$/.exec(res.headers.etag ?? '');
+ if (!match) throw new Error('서버의 revision 응답이 올바르지 않습니다.');
+ const revision = revisionText(match[1]);
+ finish(null, { revision, bytes: Buffer.concat(chunks, size) });
+ } catch (error) { finish(error); }
+ });
+ });
+ const deadline = setTimeout(() => {
+ const error = new Error('원격 작업 시간 초과: 저장 완료 여부는 다시 확인해야 합니다.');
+ finish(error);
+ req.destroy(error);
+ }, 12000);
+ req.on('error', (error) => finish(error));
+ req.end(body);
+ });
+}
+
+export async function pushProject(target, expected, project) {
+ revisionText(expected, true);
+ const text = JSON.stringify(project);
+ parseProject(text);
+ const body = Buffer.from(text, 'utf8');
+ const headers = expected === '0' ? { 'If-None-Match': '*' } : { 'If-Match': `"${expected}"` };
+ const result = await request(target, 'PUT', body, headers);
+ return result.revision;
+}
+
+export async function pullProject(target) {
+ const result = await request(target, 'GET');
+ const text = new TextDecoder('utf-8', { fatal: true }).decode(result.bytes);
+ const project = parseProject(text);
+ if (project.version !== 2) throw new Error('현재 배치를 포함한 version 2 작업물이 필요합니다.');
+ return { project, revision: result.revision };
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/compiler.mjs b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/compiler.mjs
new file mode 100644
index 0000000..6aec335
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/compiler.mjs
@@ -0,0 +1,496 @@
+// Pure's experimental scalar interaction language. No host code is evaluated.
+const LIMITS = Object.freeze({ sourceBytes: 32768, states: 32, inputs: 8,
+ views: 24, handlers: 64, instructions: 512, depth: 64, stack: 64 });
+const RESERVED = new Set(['frame', 'dt', 'event_x', 'event_y', 'event_value', 'min', 'max', 'clamp']);
+const BINARY = new Map([
+ ['||', [1, 15]], ['&&', [2, 14]], ['==', [3, 12]], ['!=', [3, 13]],
+ ['<', [4, 8]], ['<=', [4, 9]], ['>', [4, 10]], ['>=', [4, 11]],
+ ['+', [5, 3]], ['-', [5, 4]], ['*', [6, 5]], ['/', [6, 6]],
+]);
+const FUNCTIONS = { min: [2, 17], max: [2, 18], clamp: [3, 19] };
+const VIEW_FIELDS = { box: ['x', 'y', 'width', 'height'],
+ circle: ['x', 'y', 'radius'], text: ['x', 'y', 'value'] };
+
+function fail(token, message) {
+ const error = new Error(`${message} (${token.line}:${token.column})`);
+ error.line = token.line;
+ error.column = token.column;
+ throw error;
+}
+
+function lex(source) {
+ const tokens = [];
+ let offset = 0, line = 1, column = 1;
+ const advance = () => {
+ const char = source[offset++];
+ if (char === '\n') { line++; column = 1; } else column++;
+ return char;
+ };
+ while (offset < source.length) {
+ const char = source[offset];
+ if (char === ' ' || char === '\t' || char === '\r') { advance(); continue; }
+ if (char === '#') { while (offset < source.length && source[offset] !== '\n') advance(); continue; }
+ const token = { line, column };
+ if (char === '\n') { advance(); tokens.push({ ...token, kind: 'nl' }); continue; }
+ if (char === '"') {
+ advance();
+ let value = '', closed = false;
+ while (offset < source.length) {
+ const next = advance();
+ if (next === '"') { closed = true; break; }
+ if (next === '\n' || next === '\r') fail(token, 'Strings must fit on one line');
+ if (next === '\\') {
+ const escaped = advance();
+ const escapes = { n: '\n', r: '\r', t: '\t', '"': '"', '\\': '\\' };
+ if (!Object.hasOwn(escapes, escaped)) fail(token, 'Unsupported string escape');
+ value += escapes[escaped];
+ } else value += next;
+ }
+ if (!closed) fail(token, 'Unterminated string');
+ tokens.push({ ...token, kind: 'string', value }); continue;
+ }
+ const remaining = source.slice(offset);
+ const number = remaining.match(/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/);
+ if (number) {
+ const value = Number(number[0]);
+ if (!Number.isFinite(value)) fail(token, 'Number must be finite');
+ for (let i = 0; i < number[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'number', value }); continue;
+ }
+ const name = remaining.match(/^[A-Za-z_][A-Za-z_0-9]*/);
+ if (name) {
+ for (let i = 0; i < name[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'name', value: name[0] }); continue;
+ }
+ const pair = source.slice(offset, offset + 2);
+ if (['<=', '>=', '==', '!=', '&&', '||'].includes(pair)) {
+ advance(); advance(); tokens.push({ ...token, kind: pair }); continue;
+ }
+ if ('=+-*/!<>(){},.;:'.includes(char)) {
+ advance(); tokens.push({ ...token, kind: char }); continue;
+ }
+ fail(token, `Unexpected character ${JSON.stringify(char)}`);
+ }
+ tokens.push({ kind: 'eof', line, column });
+ return tokens;
+}
+
+class Parser {
+ constructor(tokens) { this.tokens = tokens; this.position = 0; this.depth = 0; }
+ peek() { return this.tokens[this.position]; }
+ take() { return this.tokens[this.position++]; }
+ is(kind, value) { return this.peek().kind === kind && (value === undefined || this.peek().value === value); }
+ expect(kind, description = kind) {
+ if (!this.is(kind)) fail(this.peek(), `Expected ${description}`);
+ return this.take();
+ }
+ newlines() { while (this.is('nl')) this.take(); }
+ separators() { while (this.is('nl') || this.is(';')) this.take(); }
+ end() {
+ if (!['nl', ';', '}', 'eof'].includes(this.peek().kind)) fail(this.peek(), 'Expected newline or semicolon');
+ this.separators();
+ }
+ reference(token) {
+ if (!this.is('.')) return token.value;
+ this.take();
+ return `${token.value}.${this.expect('name', 'field name').value}`;
+ }
+ initial() {
+ let sign = 1;
+ if (this.is('-') || this.is('+')) sign = this.take().kind === '-' ? -1 : 1;
+ return sign * this.expect('number', 'numeric state initializer').value;
+ }
+ node(token, properties, children = []) {
+ const depth = 1 + Math.max(0, ...children.map(child => child.depth));
+ if (depth > LIMITS.depth) fail(token, 'Expression nesting exceeds 64');
+ return { token, depth, ...properties };
+ }
+ expression(minimum = 0, multiline = false) {
+ if (++this.depth > LIMITS.depth) fail(this.peek(), 'Expression nesting exceeds 64');
+ if (multiline) this.newlines();
+ const token = this.take();
+ let left;
+ if (token.kind === 'number') left = this.node(token, { kind: 'constant', value: token.value });
+ else if (token.kind === '-' || token.kind === '!') {
+ const child = this.expression(7, multiline);
+ left = this.node(token, { kind: 'unary', op: token.kind === '-' ? 7 : 16, child }, [child]);
+ } else if (token.kind === '(') {
+ left = this.expression(0, true); this.newlines(); this.expect(')');
+ } else if (token.kind === 'name') {
+ if (Object.hasOwn(FUNCTIONS, token.value) && this.is('(')) {
+ this.take();
+ const args = [];
+ this.newlines();
+ if (!this.is(')')) {
+ for (;;) {
+ args.push(this.expression(0, true)); this.newlines();
+ if (!this.is(',')) break;
+ this.take();
+ }
+ }
+ this.expect(')');
+ if (args.length !== FUNCTIONS[token.value][0]) fail(token, `${token.value} expects ${FUNCTIONS[token.value][0]} arguments`);
+ left = this.node(token, { kind: 'call', op: FUNCTIONS[token.value][1], args }, args);
+ } else left = this.node(token, { kind: 'reference', name: this.reference(token) });
+ } else fail(token, 'Expected a number, state, or expression');
+ for (;;) {
+ if (multiline) this.newlines();
+ const entry = BINARY.get(this.peek().kind);
+ if (!entry || entry[0] < minimum) break;
+ const operator = this.take();
+ const right = this.expression(entry[0] + 1, multiline);
+ left = this.node(operator, { kind: 'binary', op: entry[1], left, right }, [left, right]);
+ }
+ this.depth--;
+ return left;
+ }
+ block(depth = 0) {
+ if (depth >= LIMITS.depth) fail(this.peek(), 'Handler nesting exceeds 64');
+ this.newlines(); this.expect('{'); this.separators();
+ const statements = [];
+ while (!this.is('}')) {
+ const token = this.expect('name', 'assignment, if, or closing brace');
+ if (token.value === 'if' && !this.is('=')) {
+ const condition = this.expression();
+ const body = this.block(depth + 1);
+ statements.push({ kind: 'if', token, condition, body });
+ } else {
+ const name = this.reference(token);
+ this.expect('=');
+ statements.push({ kind: 'assign', token, name, expression: this.expression() });
+ }
+ this.end();
+ }
+ this.take();
+ return statements;
+ }
+ parse() {
+ const declarations = [];
+ this.separators();
+ while (!this.is('eof')) {
+ const token = this.expect('name', 'declaration');
+ const kind = token.value;
+ if (kind === 'state') {
+ const name = this.expect('name', 'state name'); this.expect('=');
+ declarations.push({ kind, token, name, initial: this.initial() });
+ } else if (kind === 'record') {
+ const name = this.expect('name', 'record type'); this.newlines(); this.expect('{'); this.separators();
+ const fields = [];
+ while (!this.is('}')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,fields});
+ } else if (kind === 'item') {
+ const name = this.expect('name', 'item name'); this.expect('=');
+ const type = this.expect('name', 'record type'); this.expect('('); this.newlines();
+ const fields = [];
+ while (!this.is(')')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.newlines();
+ if (!this.is(',')) break;
+ this.take(); this.newlines();
+ }
+ this.expect(')'); declarations.push({kind,token,name,type,fields});
+ } else if (kind === 'rule') {
+ const name = this.expect('name', 'rule name'); this.expect('(');
+ const parameter = this.expect('name', 'record parameter'); this.expect(':');
+ const type = this.expect('name', 'record type'); this.expect(')');
+ declarations.push({kind,token,name,parameter,type,body:this.block()});
+ } else if (kind === 'input') {
+ const name = this.expect('name', 'input name'); this.expect('=');
+ const key = this.expect('name', 'keyboard code or pointer(view)');
+ if (key.value === 'value') {
+ declarations.push({kind,token,name,valueInput:true}); this.end(); continue;
+ }
+ if (key.value === 'pointer') {
+ if (this.is('{')) {
+ this.take(); this.separators(); const routes = [];
+ while (!this.is('}')) {
+ const target = this.expect('name', 'view ID'); this.expect(':');
+ const item = this.expect('name', 'item name'); routes.push({target,item}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,routes}); this.end(); continue;
+ }
+ this.expect('(');
+ const target = this.expect('name', 'view ID'); this.expect(')');
+ declarations.push({ kind, token, name, target });
+ this.end(); continue;
+ }
+ if (!/^(?:Space|Enter|Arrow(?:Left|Right|Up|Down)|Key[A-Z]|Digit[0-9])$/.test(key.value)) fail(key, 'Unsupported keyboard code');
+ declarations.push({ kind, token, name, key });
+ } else if (Object.hasOwn(VIEW_FIELDS, kind)) {
+ const name = this.expect('name', 'view ID'); this.expect('(');
+ const expressions = [];
+ for (let i = 0; i < VIEW_FIELDS[kind].length; i++) {
+ if (i) { this.newlines(); this.expect(','); }
+ expressions.push(this.expression(0, true));
+ }
+ this.newlines();
+ let color, prefix = '';
+ if (kind !== 'text') {
+ this.expect(','); this.newlines();
+ const value = this.expect('string', 'literal hex color');
+ if (!/^#[0-9a-fA-F]{6}$/.test(value.value)) fail(value, 'Color must use six hexadecimal digits, such as "#356548"');
+ color = value.value;
+ } else if (this.is(',')) { this.take(); this.newlines(); prefix = this.expect('string', 'literal text prefix').value; }
+ this.newlines(); this.expect(')');
+ declarations.push({ kind: 'view', type: kind, token, name, expressions, color, prefix });
+ } else if (kind === 'on') {
+ const event = this.expect('name', 'input name or frame');
+ let edge;
+ if (event.value !== 'frame') {
+ this.expect('.'); edge = this.expect('name', 'down, up, move or cancel');
+ if (!['down', 'up', 'move', 'cancel', 'change'].includes(edge.value)) fail(edge, 'Expected down or up, move, cancel or change');
+ }
+ if (this.is('name', 'use')) {
+ this.take(); const rule = this.expect('name', 'rule name'); this.expect('(');
+ const item = this.expect('name', 'item name or input.target');
+ const argument = this.reference(item); this.expect(')');
+ declarations.push({kind:'handler',token,event,edge,rule,item,argument});
+ } else declarations.push({ kind: 'handler', token, event, edge, body: this.block() });
+ } else fail(token, `Unknown declaration ${kind}`);
+ this.end();
+ }
+ return declarations;
+ }
+}
+
+export function compile(source) {
+ if (typeof source !== 'string') fail({ line: 1, column: 1 }, 'Source must be a string');
+ const sourceBytes = new TextEncoder().encode(source).length;
+ if (sourceBytes > LIMITS.sourceBytes) fail({ line: 1, column: 1 }, 'Source exceeds 32768 UTF-8 bytes');
+ const declarations = new Parser(lex(source)).parse();
+ const program = { states: [], inputs: [], instructions: [], handlers: [], views: [], pointerTargets: [], metrics: {} };
+ const states = new Map(), inputs = new Map(), views = new Set(), keys = new Set(), targets = new Set();
+ const records = new Map(), items = new Map(), rules = new Map();
+ const scalarNames = new Set(declarations.filter(d => d.kind === 'state').map(d => d.name.value));
+ for (const declaration of declarations) {
+ if (!['record','rule'].includes(declaration.kind)) continue;
+ const {name,fields,kind} = declaration, symbols = kind === 'record' ? records : rules;
+ if (RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (kind === 'record') {
+ if (!fields.length || fields.length > 8) fail(name, 'A record needs 1..8 fields');
+ const used = new Set();
+ for (const field of fields) {
+ if (used.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ if (RESERVED.has(field.name.value)) fail(field.name, `Reserved name ${field.name.value}`);
+ used.add(field.name.value);
+ }
+ }
+ symbols.set(name.value, declaration);
+ }
+ let handlerCount = 0;
+ for (const declaration of declarations) {
+ const { kind, name, token } = declaration;
+ if (name && RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (kind === 'record' || kind === 'rule') continue;
+ if (kind === 'item') {
+ if (items.has(name.value) || scalarNames.has(name.value)) fail(name, `Duplicate state/item ${name.value}`);
+ const record = records.get(declaration.type.value);
+ if (!record) fail(declaration.type, `Unknown record ${declaration.type.value}`);
+ const overrides = new Map();
+ for (const field of declaration.fields) {
+ if (!record.fields.some(f => f.name.value === field.name.value)) fail(field.name, `Unknown field ${field.name.value}`);
+ if (overrides.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ overrides.set(field.name.value, field.initial);
+ }
+ const base = states.size;
+ for (const field of record.fields) {
+ if (states.size >= LIMITS.states) fail(name, 'At most 32 states are allowed, including item fields');
+ const qualified = `${name.value}.${field.name.value}`, index = states.size;
+ states.set(qualified,index);
+ program.states.push({name:qualified,initial:overrides.has(field.name.value) ? overrides.get(field.name.value) : field.initial,line:token.line});
+ }
+ items.set(name.value,{type:declaration.type.value,base,count:record.fields.length});
+ } else if (kind === 'state' || kind === 'input') {
+ const symbols = kind === 'state' ? states : inputs;
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (symbols.size >= LIMITS[`${kind}s`]) fail(name, `At most ${LIMITS[`${kind}s`]} ${kind}s are allowed`);
+ symbols.set(name.value, symbols.size);
+ if (kind === 'state') program.states.push({ name: name.value, initial: declaration.initial, line: token.line });
+ else if (declaration.valueInput) {
+ program.inputs.push({name:name.value,kind:'value',line:token.line});
+ } else if (declaration.routes) {
+ if (!declaration.routes.length) fail(name, 'A pointer group needs at least one target');
+ program.inputs.push({name:name.value, routes:[], line:token.line});
+ } else if (declaration.target) {
+ const target = declaration.target;
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ targets.add(target.value);
+ program.inputs.push({ name: name.value, target: target.value, line: token.line });
+ } else {
+ if (keys.has(declaration.key.value)) fail(declaration.key, `Duplicate keyboard code ${declaration.key.value}`);
+ keys.add(declaration.key.value);
+ program.inputs.push({ name: name.value, key: declaration.key.value, line: token.line });
+ }
+ } else if (kind === 'view') {
+ if (views.has(name.value)) fail(name, `Duplicate view ID ${name.value}`);
+ if (views.size >= LIMITS.views) fail(name, 'At most 24 views are allowed');
+ views.add(name.value);
+ } else if (++handlerCount > LIMITS.handlers) fail(token, 'At most 64 handlers are allowed');
+ }
+ for (const declaration of declarations) {
+ if (declaration.target && !views.has(declaration.target.value))
+ fail(declaration.target, `Unknown pointer target ${declaration.target.value}`);
+ }
+ const routedItems = new Set();
+ for (const declaration of declarations) {
+ if (!declaration.routes) continue;
+ const input = inputs.get(declaration.name.value), resolved = program.inputs[input];
+ let type;
+ for (const {target,item:token} of declaration.routes) {
+ if (!views.has(target.value)) fail(target, `Unknown pointer target ${target.value}`);
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ const item = items.get(token.value);
+ if (!item) fail(token, `Unknown item ${token.value}`);
+ if (type && type !== item.type) fail(token, 'Pointer group targets must share one record type');
+ if (routedItems.has(token.value)) fail(token, `Item ${token.value} already has a pointer route`);
+ targets.add(target.value); routedItems.add(token.value); type = item.type;
+ const route = program.pointerTargets.length;
+ if (route >= 24) fail(target, 'At most 24 pointer targets are allowed');
+ program.pointerTargets.push({input,base:item.base,count:item.count});
+ resolved.routes.push({target:target.value, item:token.value, route});
+ }
+ resolved.type = type;
+ }
+ for (const rule of rules.values()) {
+ if (!records.has(rule.type.value)) fail(rule.type, `Unknown record ${rule.type.value}`);
+ if (RESERVED.has(rule.parameter.value)) fail(rule.parameter, `Reserved name ${rule.parameter.value}`);
+ }
+ let pointHandler = false, valueHandler = false;
+ let parameters = null;
+ let parameterPrefix = null;
+ let stack = 0, maxStack = 0;
+ const emit = (op, token, arg = 0, value = 0, delta = 0) => {
+ if (program.instructions.length >= LIMITS.instructions) fail(token, 'At most 512 instructions are allowed');
+ stack += delta;
+ if (stack < 0 || stack > LIMITS.stack) fail(token, 'Expression stack exceeds 64');
+ maxStack = Math.max(maxStack, stack);
+ program.instructions.push({ op, arg, value, line: token.line });
+ };
+ const expression = (node, binding = false) => {
+ const { token } = node;
+ if (node.kind === 'constant') emit(0, token, 0, node.value, 1);
+ else if (node.kind === 'reference') {
+ if (node.name === 'event_value') {
+ if (binding || !valueHandler) fail(token, 'event_value is only available in value change handlers');
+ emit(26, token, 0, 0, 1);
+ } else if (node.name === 'event_x' || node.name === 'event_y') {
+ if (binding || !pointHandler) fail(token, 'event_x and event_y are only available in pointer handlers');
+ emit(node.name === 'event_x' ? 22 : 23, token, 0, 0, 1);
+ } else if (node.name === 'dt') {
+ if (binding) fail(token, 'dt is only available in handlers');
+ emit(2, token, 0, 0, 1);
+ } else {
+ if (parameterPrefix && node.name.startsWith(parameterPrefix) && !parameters.has(node.name))
+ fail(token, `Unknown parameter field ${node.name}`);
+ if (parameters?.has(node.name)) {
+ emit(24, token, parameters.get(node.name), 0, 1);
+ return;
+ }
+ if (!states.has(node.name)) fail(token, `Unknown state ${node.name}`);
+ emit(1, token, states.get(node.name), 0, 1);
+ }
+ } else if (node.kind === 'unary') { expression(node.child, binding); emit(node.op, token); }
+ else if (node.kind === 'binary') {
+ expression(node.left, binding); expression(node.right, binding); emit(node.op, token, 0, 0, -1);
+ } else {
+ for (const arg of node.args) expression(arg, binding);
+ emit(node.op, token, 0, 0, 1 - node.args.length);
+ }
+ };
+ const statements = body => {
+ for (const statement of body) {
+ if (statement.kind === 'assign') {
+ if (parameterPrefix && statement.name.startsWith(parameterPrefix) && !parameters.has(statement.name))
+ fail(statement.token, `Unknown parameter field ${statement.name}`);
+ const parameter = parameters?.get(statement.name);
+ if (parameter === undefined && !states.has(statement.name)) fail(statement.token, `Unknown state ${statement.name}`);
+ expression(statement.expression);
+ emit(parameter === undefined ? 20 : 25, statement.token, parameter === undefined ? states.get(statement.name) : parameter, 0, -1);
+ } else {
+ expression(statement.condition);
+ const branch = program.instructions.length;
+ emit(21, statement.token, 0, 0, -1);
+ statements(statement.body);
+ program.instructions[branch].arg = program.instructions.length;
+ }
+ }
+ };
+ const bodies = new Map();
+ function ruleBody(rule) {
+ if (bodies.has(rule.name.value)) return bodies.get(rule.name.value);
+ parameterPrefix = `${rule.parameter.value}.`;
+ parameters = new Map(records.get(rule.type.value).fields.map((field,index) => [`${rule.parameter.value}.${field.name.value}`,index]));
+ // A shared body may read coordinates; every binding is checked below.
+ pointHandler = true; valueHandler = true; stack = 0;
+ const start = program.instructions.length;
+ statements(rule.body);
+ const length = program.instructions.length - start;
+ const point = program.instructions.slice(start).some(op => op.op === 22 || op.op === 23);
+ parameters = null; parameterPrefix = null;
+ const value = program.instructions.slice(start).some(op => op.op === 26);
+ const body = {start,length,point,value}; bodies.set(rule.name.value,body); return body;
+ }
+ for (const declaration of declarations) {
+ if (declaration.kind === 'handler') {
+ let event = 0;
+ pointHandler = false; valueHandler = false;
+ if (declaration.event.value !== 'frame') {
+ if (!inputs.has(declaration.event.value)) fail(declaration.event, `Unknown input ${declaration.event.value}`);
+ const index = inputs.get(declaration.event.value), edge = declaration.edge.value;
+ pointHandler = Boolean(program.inputs[index].target || program.inputs[index].routes);
+ valueHandler = program.inputs[index].kind === 'value';
+ if (valueHandler !== (edge === 'change')) fail(declaration.edge, 'Value inputs require change; change requires a value input');
+ if (!pointHandler && (edge === 'move' || edge === 'cancel')) fail(declaration.edge, 'move and cancel require a pointer input');
+ event = edge === 'change' ? 33 + index : edge === 'move' ? 17 + index : edge === 'cancel' ? 25 + index : 1 + index * 2 + (edge === 'up' ? 1 : 0);
+ }
+ if (declaration.rule) {
+ const rule = rules.get(declaration.rule.value);
+ const routed = declaration.argument.includes('.');
+ const input = program.inputs[inputs.get(declaration.event.value)];
+ if (routed && (!input?.routes || declaration.argument !== `${declaration.event.value}.target`))
+ fail(declaration.item, 'Use the current pointer group target');
+ const item = routed ? {type:input.type, count:records.get(input.type).fields.length} : items.get(declaration.item.value);
+ if (!rule) fail(declaration.rule, `Unknown rule ${declaration.rule.value}`);
+ if (!item) fail(declaration.item, `Unknown item ${declaration.item.value}`);
+ if (item.type !== rule.type.value) fail(declaration.item, `Rule ${rule.name.value} requires ${rule.type.value}`);
+ const pointer = pointHandler, value = valueHandler;
+ const body = ruleBody(rule);
+ if (body.value && !value) fail(declaration.rule, 'Value-reading rules require a value input');
+ if (body.point && !pointer) fail(declaration.rule, 'Coordinate-reading rules require a pointer input');
+ program.handlers.push({event,start:body.start,length:body.length,line:declaration.token.line,parameterBase:routed ? 255 : item.base,parameterCount:item.count});
+ } else {
+ const start = program.instructions.length;
+ stack = 0; statements(declaration.body);
+ program.handlers.push({ event, start, length: program.instructions.length - start, line: declaration.token.line });
+ }
+ } else if (declaration.kind === 'view') {
+ const view = { id: declaration.name.value, type: declaration.type, line: declaration.token.line, bindings: {} };
+ if (view.type === 'text') view.prefix = declaration.prefix;
+ else view.color = declaration.color;
+ declaration.expressions.forEach((node, index) => {
+ const start = program.instructions.length;
+ stack = 0; expression(node, true);
+ view.bindings[VIEW_FIELDS[view.type][index]] = { start, length: program.instructions.length - start };
+ });
+ program.views.push(view);
+ }
+ }
+ // Unused definitions still receive name/type checking, but reserve no VM body.
+ for (const rule of rules.values()) {
+ if (bodies.has(rule.name.value)) continue;
+ const instructions = program.instructions, previousMax = maxStack;
+ program.instructions = [];
+ ruleBody(rule);
+ program.instructions = instructions; maxStack = previousMax;
+ }
+ program.metrics = { sourceBytes, sourceLines: source === '' ? 0 : source.split('\n').length,
+ states: states.size, inputs: inputs.size, views: views.size,
+ handlers: program.handlers.length, instructions: program.instructions.length, maxStack };
+ return program;
+}
+
+export { LIMITS };
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/core.wasm b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/core.wasm
new file mode 100644
index 0000000..79c50a8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/core.wasm
Binary files differ
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/project.mjs b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/project.mjs
new file mode 100644
index 0000000..861e0fc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/project.mjs
@@ -0,0 +1,47 @@
+import { compile } from './compiler.mjs';
+
+// Two escaped source strings plus up to 32 generated item.field names. A long
+// schema field can appear in every item without repeating in the source text.
+export const MAX_PROJECT_BYTES = (2 * 6 + 32) * 32768 + 8192;
+const encoder = new TextEncoder();
+function sourceText(value, label) {
+ if (typeof value !== 'string' || encoder.encode(value).length > 32768)
+ throw new Error(`${label}: UTF-8 32 KiB 이하의 코드가 필요합니다.`);
+ return value;
+}
+
+// No runtime mutation. Validate every saved value before opening core staging.
+export function validateDocument(document) {
+ if (!document || typeof document !== 'object' || Array.isArray(document) ||
+ document.format !== 'pure-workbench' || document.version !== 2)
+ throw new Error('배치 파일 형식이 맞지 않습니다. pure-workbench version 2가 필요합니다.');
+ const source = sourceText(document.source, '적용된 코드');
+ const draft = sourceText(Object.hasOwn(document, 'draft') ? document.draft : source, '편집 중인 코드');
+ const program = compile(source);
+ if (!Array.isArray(document.states) || document.states.length !== program.states.length)
+ throw new Error('저장된 상태 목록이 적용된 코드와 일치하지 않습니다.');
+ const values = new Map();
+ for (const entry of document.states) {
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry) || typeof entry.name !== 'string' || values.has(entry.name))
+ throw new Error('상태 이름이 잘못됐거나 중복됐습니다.');
+ const value = entry.value === '-0' ? -0 : entry.value;
+ if (typeof value !== 'number' || !Number.isFinite(value)) throw new Error('상태 값은 유한한 숫자여야 합니다.');
+ values.set(entry.name, value);
+ }
+ for (const state of program.states)
+ if (!values.has(state.name)) throw new Error(`저장된 상태가 없습니다: ${state.name}`);
+ return { source, draft, program, values: program.states.map(state => values.get(state.name)) };
+}
+
+export function parseProject(text) {
+ if (typeof text !== 'string' || encoder.encode(text).length > MAX_PROJECT_BYTES)
+ throw new Error('작업 파일이 너무 큽니다.');
+ let project;
+ try { project = JSON.parse(text); } catch { throw new Error('올바른 JSON 파일이 아닙니다.'); }
+ if (!project || typeof project !== 'object' || Array.isArray(project) || project.format !== 'pure-workbench')
+ throw new Error('Pure 작업물 형식이 아닙니다.');
+ if (project.version === 1) sourceText(project.source, '코드');
+ else if (project.version === 2) validateDocument(project);
+ else throw new Error('지원하지 않는 작업 파일 버전입니다.');
+ return project;
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/runtime.mjs b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/runtime.mjs
new file mode 100644
index 0000000..d8d6618
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/sources/prototypes/workbench/web/runtime.mjs
@@ -0,0 +1,350 @@
+import { compile } from './compiler.mjs';
+import { validateDocument } from './project.mjs';
+
+const messages = [
+ '', '실행기의 용량 한도를 넘었습니다.', '실행 정의가 유효하지 않습니다.',
+ '계산 스택의 범위를 벗어났습니다.', '0으로 나눌 수 없습니다.',
+ '계산 결과가 유한한 수의 범위를 벗어났습니다.', '조건 분기 범위가 유효하지 않습니다.',
+ '존재하지 않는 상태를 참조했습니다.', '시간 간격이 유효하지 않습니다.',
+ '정의되지 않은 입력 사건입니다.',
+];
+const sourceLimit = 32768;
+
+function problem(message, line = null, column = null) {
+ return Object.assign(new Error(message), { line, column });
+}
+
+function freezeProgram(value) {
+ if (value && typeof value === 'object') {
+ for (const child of Object.values(value)) freezeProgram(child);
+ Object.freeze(value);
+ }
+ return value;
+}
+
+export async function createRuntime(wasmBytes, evaluationOptions = {}) {
+ if (wasmBytes === undefined) {
+ const response = await fetch(new URL('./core.wasm', import.meta.url), { cache: 'no-store' });
+ if (!response.ok) throw new Error(`실행기를 불러오지 못했습니다 (HTTP ${response.status}).`);
+ wasmBytes = await response.arrayBuffer();
+ }
+ const module = await WebAssembly.compile(wasmBytes);
+ if (WebAssembly.Module.imports(module).length) throw new Error('이 실행기는 호스트 함수 없이 동작해야 합니다.');
+ const { exports: core } = await WebAssembly.instantiate(module, {});
+ if (typeof core.eval_bounded !== 'function' || typeof core.abort_program !== 'function' || typeof core.dispatch_point !== 'function' || typeof core.put_restored_value !== 'function' || typeof core.commit_restored_program !== 'function' || typeof core.bind_handler !== 'function' || typeof core.put_pointer_target !== 'function' || typeof core.bind_target_handler !== 'function' || typeof core.dispatch_target !== 'function' || typeof core.dispatch_value !== 'function')
+ throw new Error('실행기 버전이 맞지 않습니다. 새로고침하거나 core.wasm을 다시 빌드하세요.');
+ core.reset_all();
+ let program = null;
+ let appliedSource = '';
+ let lastEvent = null;
+ // Keep a failed event visible through its release/focus-loss cleanup.
+ // The active program can clear this diagnostic by apply or explicit reset.
+ let lastFailure = null;
+ const held = new Map();
+ const points = new Map();
+ let presenting = false;
+ let bindings = [];
+ let pointRoutes = new Map();
+ // One bounded publication buffer, never exposed to callers. No state mirror.
+ let displayValues = null, displayValid = null;
+ function available() {
+ if (presenting) throw new Error('출력 전달 중에는 실행기를 다시 호출할 수 없습니다.');
+ }
+ let evaluationPolicy = { cacheEntries: 0, historyEntries: 8, workLimit: 2048 };
+
+ function checked(code, line = null) {
+ if (code !== 0) throw problem(messages[code] || `실행기 오류 ${code}`, line);
+ }
+ function inputIndex(name) {
+ const index = program?.inputs.findIndex((input) => input.name === name) ?? -1;
+ if (index < 0) throw new Error(`정의되지 않은 입력: ${name}`);
+ return index;
+ }
+ function dispatch(event, name, phase, source, point = null, value = undefined) {
+ const status = value !== undefined ? core.dispatch_value(event, value) : point ? (point.route === undefined ? core.dispatch_point(event, point.x, point.y)
+ : core.dispatch_target(event, point.route, point.x, point.y)) : core.dispatch(event, event === 0 ? 1 / 60 : 0);
+ const pc = core.info(2) >>> 0;
+ lastEvent = { name, phase, source, status,
+ line: program?.instructions[pc]?.line ?? null, ops: core.info(3) >>> 0 };
+ if (point) { lastEvent.x = point.x; lastEvent.y = point.y; if (point.target) lastEvent.target = point.target; }
+ if (value !== undefined) lastEvent.value = value;
+ if (status) lastFailure = { ...lastEvent };
+ return status;
+ }
+
+ function evaluateDisplay() {
+ core.begin_evaluation(evaluationPolicy.workLimit);
+ if (!bindings.length) return null;
+ displayValues ??= new Float64Array(96);
+ displayValid ??= new Uint8Array(24);
+ let error = null, slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ displayValid[i] = 1;
+ for (const [name, binding] of bindings[i]) {
+ const value = core.eval_bounded(binding.start, binding.length);
+ if (core.evaluation_info(0) === 10) {
+ displayValid.fill(0);
+ return { code: 101, line: view.line,
+ message: '표시 계산의 작업량 한도를 넘었습니다. 한도를 늘리거나 표시식을 줄이세요.' };
+ }
+ if (!Number.isFinite(value) || ((name === 'width' || name === 'height' || name === 'radius') && value < 0)) {
+ error ??= { line: view.line, message: `${view.id}.${name}: 표시할 수 없는 값입니다. 0 나눗셈이나 음수 크기를 확인하세요.` };
+ displayValid[i] = 0;
+ }
+ displayValues[slot++] = value;
+ }
+ }
+ return error;
+ }
+
+ function status(viewError) {
+ const executionError = lastFailure?.status || 0;
+ return {
+ tick: core.info(0) >>> 0, revision: core.info(4) >>> 0,
+ displayError: viewError ? { code: viewError.code || 100, ...viewError } : null,
+ lastError: executionError || (viewError ? viewError.code || 100 : 0),
+ errorMessage: executionError ? messages[executionError] || `실행 오류 ${executionError}` : viewError?.message || '',
+ errorLine: executionError ? lastFailure.line : viewError?.line ?? null,
+ lastOps: core.info(3) >>> 0, successfulEvents: core.info(9) >>> 0,
+ held: [...held.keys()], lastEvent: lastEvent ? { ...lastEvent } : null,
+ lastFailure: lastFailure ? { ...lastFailure } : null,
+ memory: {
+ linearBytes: core.memory.buffer.byteLength,
+ reservedEngineBytes: core.layout(0), programReservedBytes: core.layout(1),
+ instructionBytes: core.layout(2), handlerBytes: core.layout(3),
+ activeIRBytes: core.layout(4), activeStateBytes: core.layout(5),
+ stagingReservedBytes: core.layout(6), evalStackBytes: core.layout(7),
+ pointerTargetBytes: core.layout(8), pointerTargets: core.layout(9),
+ },
+ };
+ }
+
+ function load(next, source, restored = null) {
+ const oldIds = new Map(restored ? [] : program?.states.map((state, index) => [state.name, index]) ?? []);
+ checked(core.begin_program(next.states.length, next.inputs.length));
+ try {
+ for (let index = 0; index < next.states.length; index++) {
+ const state = next.states[index];
+ checked(core.put_state(index, state.initial, oldIds.get(state.name) ?? -1), state.line);
+ if (restored) checked(core.put_restored_value(index, restored[index]), state.line);
+ }
+ for (const op of next.instructions) checked(core.put_instruction(op.op, op.arg, op.value), op.line);
+ for (const target of next.pointerTargets) checked(core.put_pointer_target(target.input, target.base, target.count));
+ for (const [index, handler] of next.handlers.entries()) {
+ checked(core.put_handler(handler.event, handler.start, handler.length), handler.line);
+ if (handler.parameterCount)
+ checked(handler.parameterBase === 255 ? core.bind_target_handler(index, handler.parameterCount)
+ : core.bind_handler(index, handler.parameterBase, handler.parameterCount), handler.line);
+ }
+ checked(restored ? core.commit_restored_program() : core.commit_program());
+ } catch (error) {
+ core.abort_program();
+ throw error;
+ }
+ pointRoutes = new Map(next.inputs.flatMap(input => (input.routes ?? []).map(route => [route.target, route])));
+ program = next;
+ bindings = next.views.map(view => Object.entries(view.bindings));
+ appliedSource = source;
+ lastEvent = null;
+ lastFailure = null;
+ }
+
+ const api = {
+ get currentProgram() { return program; },
+ configureEvaluation({ cacheEntries = evaluationPolicy.cacheEntries,
+ historyEntries = evaluationPolicy.historyEntries, workLimit = evaluationPolicy.workLimit } = {}) {
+ available();
+ for (const [name, value, maximum] of [['cacheEntries', cacheEntries, 32],
+ ['historyEntries', historyEntries, 8], ['workLimit', workLimit, 0xffffffff]]) {
+ if (!Number.isInteger(value) || value < 0 || value > maximum)
+ throw new Error(`${name}: 0~${maximum} 사이의 정수여야 합니다.`);
+ }
+ checked(core.configure_evaluation(cacheEntries, historyEntries));
+ evaluationPolicy = { cacheEntries, historyEntries, workLimit };
+ return { ...evaluationPolicy };
+ },
+ forgetEvaluation(part = 'all') {
+ available();
+ const flags = part === 'all' ? 3 : part === 'values' ? 1 : part === 'history' ? 2 : undefined;
+ if (flags === undefined) throw new Error('삭제할 기록은 values, history, all 중 하나여야 합니다.');
+ core.forget_evaluation(flags);
+ },
+ evaluationStats() {
+ return { ...evaluationPolicy, work: core.evaluation_info(1),
+ instructions: core.evaluation_info(2), cacheHits: core.evaluation_info(3),
+ reservedBytes: core.evaluation_info(6), dedicatedBytes: core.evaluation_info(7),
+ sharedBytes: core.evaluation_info(8), reuseAvailable: Boolean(core.evaluation_info(9)),
+ workspaceTagBytes: core.evaluation_info(10) };
+ },
+ apply(source) {
+ available();
+ if (typeof source !== 'string' || new TextEncoder().encode(source).length > sourceLimit) {
+ throw problem('정의는 UTF-8 기준 32,768바이트 이하의 텍스트여야 합니다.');
+ }
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 적용하세요. 현재 작업은 그대로 유지합니다.');
+ const next = freezeProgram(compile(source));
+ load(next, source);
+ return next;
+ },
+ restoreDocument(document) {
+ available();
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 복원하세요.');
+ const next = validateDocument(document);
+ load(freezeProgram(next.program), next.source, next.values);
+ return { source: next.source, draft: next.draft };
+ },
+ exportDocument(draft = appliedSource) {
+ available();
+ if (!program) throw problem('먼저 코드를 적용하세요.');
+ if (held.size) throw problem('조작을 끝낸 뒤 배치를 저장하세요.');
+ if (lastFailure) throw problem('실행 오류를 해결한 뒤 배치를 저장하세요.');
+ if (typeof draft !== 'string' || new TextEncoder().encode(draft).length > sourceLimit)
+ throw problem('편집 중인 코드는 UTF-8 32 KiB 이하여야 합니다.');
+ return { format: 'pure-workbench', version: 2, source: appliedSource, draft,
+ states: program.states.map((state, i) => {
+ const value = core.get_state(i);
+ return { name: state.name, value: Object.is(value, -0) ? '-0' : value };
+ }) };
+ },
+ reset() {
+ available();
+ held.clear();
+ points.clear();
+ core.reset_state();
+ lastEvent = null;
+ lastFailure = null;
+ },
+ frame(count = 1) {
+ available();
+ if (!Number.isInteger(count) || count < 0 || count > 600) throw new Error('프레임 수는 0~600 사이의 정수여야 합니다.');
+ if (!program) return 0;
+ for (let i = 0; i < count; i++) {
+ const code = dispatch(0, 'frame', 'frame', 'clock');
+ if (code !== 0) return code;
+ }
+ return 0;
+ },
+ down(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name) || new Set();
+ if (sources.has(source)) return 0;
+ const wasDown = sources.size > 0;
+ sources.add(source);
+ held.set(name, sources);
+ return wasDown ? 0 : dispatch(1 + index * 2, name, 'down', source);
+ },
+ up(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name);
+ if (!sources?.delete(source)) return 0;
+ if (sources.size) return 0;
+ held.delete(name);
+ return dispatch(2 + index * 2, name, 'up', source);
+ },
+ change(name, value, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind !== 'value') throw new Error('숫자 값에 연결된 입력이 아닙니다.');
+ if (!Number.isFinite(value)) throw new Error('입력 값은 유한한 숫자여야 합니다.');
+ return dispatch(33 + index, name, 'change', source, null, value);
+ },
+ point(name, phase, x, y, source = 'external', target = undefined) {
+ available();
+ const index = inputIndex(name);
+ const input = program.inputs[index];
+ if (!input.target && !input.routes) throw new Error('포인터에 연결된 입력이 아닙니다.');
+ const route = input.routes ? pointRoutes.get(target) : undefined;
+ if (input.routes && (!route || program.pointerTargets[route.route].input !== index)) throw new Error('포인터 그룹에 연결된 도형 이름이 필요합니다.');
+ if (!input.routes && target !== undefined) throw new Error('단일 포인터 입력에는 대상 인자를 지정하지 않습니다.');
+ const owner = route ? `${name}:${target}` : name;
+ if (!['down', 'move', 'up', 'cancel'].includes(phase)) throw new Error('포인터 단계는 down, move, up, cancel 중 하나여야 합니다.');
+ if (!Number.isFinite(x) || !Number.isFinite(y)) throw new Error('포인터 좌표는 유한한 숫자여야 합니다.');
+ if (typeof source !== 'string' || source.length === 0) throw new Error('포인터 출처 이름이 필요합니다.');
+ let point = points.get(owner);
+ if (phase === 'down') {
+ if (point?.source === source) return 0;
+ if (point) throw new Error('이 입력은 다른 포인터가 사용 중입니다.');
+ point = {name, source, x, y, target, route:route?.route};
+ points.set(owner, point);
+ held.set(owner, new Set([source]));
+ } else {
+ if (!point || point.source !== source) return 0;
+ point.x = x; point.y = y;
+ if (phase === 'up' || phase === 'cancel') { points.delete(owner); held.delete(owner); }
+ }
+ const event = phase === 'move' ? 17 + index : phase === 'cancel' ? 25 + index : 1 + index * 2 + (phase === 'up' ? 1 : 0);
+ return dispatch(event, name, phase, source, point);
+ },
+ releaseAll() {
+ available();
+ let firstError = 0;
+ for (const point of [...points.values()]) {
+ const status = api.point(point.name, 'cancel', point.x, point.y, point.source, point.target);
+ if (!firstError) firstError = status;
+ }
+ for (const [name, sources] of [...held]) {
+ for (const source of [...sources]) {
+ const status = api.up(name, source);
+ if (!firstError) firstError = status;
+ }
+ }
+ return firstError;
+ },
+ exportProject() {
+ return { format: 'pure-workbench', version: 1, source: appliedSource };
+ },
+ // Synchronous trusted output adapter. Callbacks run only after the whole
+ // display has been evaluated. Runtime mutation/reentrant reads are refused.
+ // Exceptions from an adapter propagate; the next call republishes all values.
+ present(target) {
+ available();
+ presenting = true;
+ try {
+ const { begin, state, view, value, end } = target;
+ for (const callback of [begin, state, view, value, end])
+ if (typeof callback !== 'function') throw new TypeError('출력 어댑터 함수가 필요합니다.');
+ const error = evaluateDisplay();
+ begin.call(target, program);
+ for (let i = 0; i < (program?.states.length ?? 0); i++) state.call(target, i, core.get_state(i));
+ let slot = 0, visible = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const valid = Boolean(displayValid[i]);
+ view.call(target, i, valid);
+ for (const [name] of bindings[i]) {
+ if (valid) value.call(target, i, name, displayValues[slot]);
+ slot++;
+ }
+ if (valid) visible++;
+ }
+ end.call(target, visible);
+ return status(error);
+ } finally { presenting = false; }
+ },
+ snapshot() {
+ available();
+ const error = evaluateDisplay();
+ const states = Object.fromEntries((program?.states ?? []).map((state, index) => [state.name, core.get_state(index)]));
+ const views = [];
+ let slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ const rendered = displayValid[i] ? { id: view.id, type: view.type, color: view.color, prefix: view.prefix } : null;
+ for (const [name] of bindings[i]) {
+ if (rendered) rendered[name] = displayValues[slot];
+ slot++;
+ }
+ if (rendered) views.push(rendered);
+ }
+ return { states, views, ...status(error) };
+ },
+ };
+ api.configureEvaluation(evaluationOptions);
+ return Object.freeze(api);
+}
diff --git a/prototypes/connections/results/2026-09-23-byte-storage/verification.json b/prototypes/connections/results/2026-09-23-byte-storage/verification.json
new file mode 100644
index 0000000..418c75a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-byte-storage/verification.json
@@ -0,0 +1,52 @@
+{
+ "date": "2026-09-23",
+ "scope": "SQL-free storage correctness, lifetimes and admission bounds; not a performance comparison",
+ "compiler": "cc (Debian 14.2.0-19) 14.2.0",
+ "os_page_size_bytes": 16384,
+ "cwd": "prototypes/connections",
+ "native_command": "make check EVIDENCE=results/2026-09-23-byte-storage/native.json",
+ "sanitized_command": "make check BUILD=build/sanitized CFLAGS='-std=c17 -O1 -g -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer' EVIDENCE=results/2026-09-23-byte-storage/sanitized.json",
+ "core_checks": {
+ "native": "passed",
+ "asan_ubsan": "passed",
+ "leak_detection_disabled": false,
+ "coverage": [
+ "partial transfer and single release",
+ "range access including actual page boundaries and nonzero mapping offsets",
+ "immutable read across replacement",
+ "budget, conflicts, empty data, revision exhaustion",
+ "invalid file rejection",
+ "failure before publication preserves prior version",
+ "failure after publication reports uncertain durability",
+ "child exit before publication preserves prior version and releases writer lock"
+ ],
+ "native_binary_sha256": "a3189c0db63960bdf7b464d3813403065d7222366c00895e8eaad66450fd2f27",
+ "sanitized_binary_sha256": "acf03ba3881be9d534fc2419abed964f27d4dbd23173a34ab3efdeb831b7547f"
+ },
+ "integration_scenarios_each": 16,
+ "source_hashes_equal": true,
+ "source_snapshots": "sources/",
+ "source_snapshots_match_records": true,
+ "final_binaries_match_records": true,
+ "native_dynamic_dependencies_ldd": [
+ "\tlinux-vdso.so.1 (0x00007ffed5098000)",
+ "\tlibc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00007ffed4e50000)",
+ "\t/lib/ld-linux-aarch64.so.1 (0x00007ffed5060000)"
+ ],
+ "initial_run": {
+ "directory": "initial/",
+ "difference": "Only test-flow.c changed: page-boundary fixture now uses actual OS page size and distinct per-page contents",
+ "original_test_sha256_verified": true
+ },
+ "limitations": [
+ "Linux AArch64 only; macOS not executed",
+ "No actual power-loss or disk-fault testing",
+ "Logical payload budget excludes page rounding, page cache, disk retention, OS sockets and client allocations",
+ "Unpublished files left by crashes are ignored but not automatically collected",
+ "Synchronous filesystem operations can delay other connections and timeout enforcement",
+ "Single-threaded control API with one cooperating process writer lock per directory",
+ "Whole-object replacement, no multi-object transaction or payload checksum",
+ "Stored files must not be mutated in place by external writers",
+ "Pure-authored external effects and automatic path optimization remain unimplemented"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/README.md b/prototypes/connections/results/2026-09-23-document-edits/README.md
new file mode 100644
index 0000000..ee6ed76
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/README.md
@@ -0,0 +1,27 @@
+# 문서 부분 변경과 micro 비용 경계
+
+2026-09-23, Linux AArch64 / GCC 14.2.0. 정확성·구조 비용 검증이며 성능 순위 자료가 아니다.
+
+- `native.json`, `sanitized.json`: 각 36개 통합 시나리오, 실행 코어와 splice 단위 검사, 바이너리·소스 해시.
+- `core.json`: 실행 전용 아카이브의 섹션·심볼·구조체 비용과 검사 상한.
+- `boundary-checks.json`: 코어만 선택한 빌드의 파일, 비용 증가 시 검사 실패, 전체 CLI/서버 ELF 비용.
+- `verification.json`: 두 빌드의 소스와 바이너리 확인, 서버 종료 시 회수 확인.
+- `sources/`: 해시가 일치하는 소스·기존 클라이언트 37개. 검증에 사용한 Workbench Wasm도 포함한다.
+
+실행 명령 (`prototypes/connections` 기준):
+
+```sh
+make all
+make check EVIDENCE=results/2026-09-23-document-edits/native.json
+make check BUILD=build/sanitized CFLAGS='-std=c17 -O1 -g -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer' EVIDENCE=results/2026-09-23-document-edits/sanitized.json
+make check-core CORE_EVIDENCE=results/2026-09-23-document-edits/core.json
+```
+
+기존 결과를 덮어쓰지 않는다. 재현 시 출력 인자를 생략하거나 새 경로를 사용한다.
+동결 소스의 `sources/prototypes/connections`에서도 같은 빌드·검사가 가능하다.
+C17 컴파일러·make·Python·Node·로컬 TCP/자식 프로세스 실행이 필요하며, 크기 검사는
+GNU 호환 ar/nm/size를 사용한다. ASan 계측물에는 release 크기 상한을 적용하지 않는다.
+
+1 MiB 문서 편집의 11 B는 입력 크레딧이다. 파일을 재작성하는 4 KiB 호스트 스택 버퍼,
+커널·파일·allocator·파서·서버 비용을 포함한 전체 메모리라고 해석하지 않는다.
+[구현, 수치 범위와 한계](../../../../docs/research/023-document-edits.md).
diff --git a/prototypes/connections/results/2026-09-23-document-edits/boundary-checks.json b/prototypes/connections/results/2026-09-23-document-edits/boundary-checks.json
new file mode 100644
index 0000000..c24fa21
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/boundary-checks.json
@@ -0,0 +1,34 @@
+{
+ "core_only_build_files": [
+ "evaluate.o",
+ "libpure-execution.a",
+ "runtime.o"
+ ],
+ "reject_smaller_budget": [
+ "domain_bytes: 200 > 199"
+ ],
+ "reject_added_dependency_and_static_state": [
+ "unexpected archive members",
+ "bss: 4096 > 0",
+ "unexpected dependencies: ['malloc']"
+ ],
+ "selected_binaries": {
+ "pure-edit": {
+ "debug_file_bytes": 177384,
+ "stripped_file_bytes": 67904,
+ "sections": " text\t data\t bss\t dec\t hex\tfilename\n 35807\t 944\t 16\t 36767\t 8f9f\t/home/eunhhu/work/pure/prototypes/connections/build/pure-edit\n",
+ "direct_dynamic_libraries": [
+ "0x0000000000000001 (NEEDED) Shared library: [libc.so.6]"
+ ]
+ },
+ "pure-connections": {
+ "debug_file_bytes": 199080,
+ "stripped_file_bytes": 68000,
+ "sections": " text\t data\t bss\t dec\t hex\tfilename\n 42761\t 1040\t 16\t 43817\t ab29\t/home/eunhhu/work/pure/prototypes/connections/build/pure-connections\n",
+ "direct_dynamic_libraries": [
+ "0x0000000000000001 (NEEDED) Shared library: [libc.so.6]"
+ ]
+ }
+ },
+ "scope": "Selected files and direct ELF dependencies, not complete dependency memory, RSS, stack or latency."
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/core.json b/prototypes/connections/results/2026-09-23-document-edits/core.json
new file mode 100644
index 0000000..8c0caf7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/core.json
@@ -0,0 +1,53 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Release object sections and C bookkeeping, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 5932,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 5012\t 0\t 0\t 5012\t 1394\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "d56c50e38c6c0949cfad069d34568da2ac45b1d60097cf9e7c4bf804f44c8128",
+ "layout_binary_sha256": "47cf1803007fc1ec85f119bd46195ad39d9f01ef0146bf5cc45e1af31eb18098",
+ "budget_sha256": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/native.json b/prototypes/connections/results/2026-09-23-document-edits/native.json
new file mode 100644
index 0000000..c9bb1d4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/native.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 31,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "07c328c98769d02d544aea2fc5389048a7620c00d9b3ea49b9c7ba45e33984b1",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "0e4ec2c78334af2056af376a6ba9aef7416a34c6d4fbd9082f4abb640e6de28c",
+ "editor_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03",
+ "binary_sha256": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "44702e9414c26d1ee336b2e36e6713560013c2c8d0091a8900042e2468f88015",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "5d08639b5a71572553bda47cbd35562805d601aaa81f20731cd9154768ec025e",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "e1735316769b4ce4d5904b9587ccfa3ebeafa26517c53dba4491191d58c97b8e",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "b5e7ed077be1333f3a948844608785dbab98bdc9c4ae6fe9c6a4805655fc9c63",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sanitized.json b/prototypes/connections/results/2026-09-23-document-edits/sanitized.json
new file mode 100644
index 0000000..0e2dbe4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sanitized.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 31,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "776be59b5e35de39587fd5a8f703160572b3a6c098a22af635e597208bba1950",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "ec0db33c9937034148d934c658c98aa98a2fdb279a92f96a2d7374e2d292468e",
+ "editor_sha256": "23ee47873d7924163ace86cad44946e71fd21a6122930f35eff1c36f5e418bdc",
+ "binary_sha256": "f145f0f30c944e400ef8d1594bd0387f42f42569290f28c7a1272a4ee8849d4c",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "44702e9414c26d1ee336b2e36e6713560013c2c8d0091a8900042e2468f88015",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "5d08639b5a71572553bda47cbd35562805d601aaa81f20731cd9154768ec025e",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "e1735316769b4ce4d5904b9587ccfa3ebeafa26517c53dba4491191d58c97b8e",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "b5e7ed077be1333f3a948844608785dbab98bdc9c4ae6fe9c6a4805655fc9c63",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/Makefile b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/Makefile
new file mode 100644
index 0000000..d1b46e2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/Makefile
@@ -0,0 +1,59 @@
+CC ?= cc
+CFLAGS ?= -O2 -g
+CFLAGS += -std=c17 -Wall -Wextra -Wpedantic -Werror
+BUILD ?= build
+
+.PHONY: all core editor server check check-core
+CORE = runtime.c evaluate.c
+HOST = store.c store-port.c
+HEADERS = runtime.h program.h store.h store-port.h flow.h result.h
+all: core editor server
+core: $(BUILD)/libpure-execution.a
+editor: $(BUILD)/pure-edit
+server: $(BUILD)/pure-connections
+
+$(BUILD):
+ mkdir -p $@
+
+$(BUILD)/pure-connections: server.c $(HOST) flow.c program.c $(CORE) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) server.c $(HOST) flow.c program.c $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/pure-edit: edit.c $(HOST) program.c $(CORE) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) edit.c $(HOST) program.c $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/runtime.o: runtime.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c runtime.c -o $@
+
+$(BUILD)/evaluate.o: evaluate.c program.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c evaluate.c -o $@
+
+$(BUILD)/libpure-execution.a: $(BUILD)/runtime.o $(BUILD)/evaluate.o
+ $(AR) rcs $@ $^
+
+$(BUILD)/test-flow: test-flow.c store.c flow.c store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_STORE_TEST test-flow.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-program: test-program.c program.c evaluate.c program.h store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-program.c program.c evaluate.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-fields: test-fields.c program.c evaluate.c program.h store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-fields.c program.c evaluate.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-runtime: test-runtime.c program.c $(CORE) $(HOST) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-runtime.c program.c $(CORE) $(HOST) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-splice: test-splice.c program.c $(CORE) $(HOST) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_STORE_TEST test-splice.c program.c $(CORE) $(HOST) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/core-layout: core-layout.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) core-layout.c $(LDFLAGS) $(LDLIBS) -o $@
+
+# Run on the release build, separately from sanitizer-instrumented objects.
+check-core: core $(BUILD)/core-layout
+ python3 check_core.py --archive $(BUILD)/libpure-execution.a --layout $(BUILD)/core-layout $(if $(CORE_EVIDENCE),--output "$(CORE_EVIDENCE)")
+
+check: $(BUILD)/test-flow $(BUILD)/test-program $(BUILD)/test-fields $(BUILD)/test-runtime $(BUILD)/test-splice $(BUILD)/pure-edit $(BUILD)/pure-connections
+ $(BUILD)/test-flow
+ $(BUILD)/test-program
+ $(BUILD)/test-fields
+ python3 check.py --server $(BUILD)/pure-connections --runtime-test $(BUILD)/test-runtime --splice-test $(BUILD)/test-splice --editor $(BUILD)/pure-edit $(if $(EVIDENCE),--output "$(EVIDENCE)")
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check.py b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check.py
new file mode 100644
index 0000000..4538995
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check.py
@@ -0,0 +1,551 @@
+#!/usr/bin/env python3
+"""Exercise local TCP, immutable byte extents, and the existing workbench CLI."""
+import argparse
+from contextlib import contextmanager
+from concurrent.futures import ThreadPoolExecutor
+import fcntl
+import hashlib
+import http.client
+import json
+import platform
+from pathlib import Path
+import select
+import socket
+import struct
+import subprocess
+import sys
+import tempfile
+import time
+from check_edits import check_edits
+
+ROOT = Path(__file__).resolve().parent
+WORKBENCH = ROOT.parent / 'workbench'
+OBJECT_LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+class Server:
+ def __init__(self, binary, storage, budget=4 * 1024 * 1024, timeout=5000, program=None):
+ self.process = subprocess.Popen([str(binary), '--store', str(storage), '--port', '0',
+ '--program', str(program or ROOT / 'examples/storage.pure'),
+ '--budget', str(budget), '--timeout-ms', str(timeout), '--send-buffer', '4096'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
+ if not select.select([self.process.stdout], [], [], 15)[0]:
+ self.process.kill()
+ raise AssertionError('server readiness timed out')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.ready = json.loads(line)
+ self.port = self.ready['port']
+ self.stats = None
+
+ def close(self):
+ if self.process.poll() is None:
+ self.process.terminate()
+ try:
+ stdout, stderr = self.process.communicate(timeout=10)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.process.communicate()
+ raise
+ assert self.process.returncode == 0, (stdout, stderr)
+ self.stats = json.loads(stderr)
+ assert self.stats['active'] == self.stats['retained_payload_bytes'] == 0
+ assert self.stats['peak_retained_payload_bytes'] <= self.stats['payload_budget']
+ assert self.stats['peak_connections'] <= 8
+
+
+@contextmanager
+def serving(*args, **kwargs):
+ server = Server(*args, **kwargs)
+ try:
+ yield server
+ finally:
+ server.close()
+
+
+def rpc(server, method, key, body=b'', expected=None):
+ headers = {'Content-Length': str(len(body))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = '*' if expected == 0 else f'"{expected}"'
+ connection = http.client.HTTPConnection('127.0.0.1', server.port, timeout=8)
+ try:
+ connection.request(method, f'/objects/{key}', body, headers)
+ response = connection.getresponse()
+ return response.status, dict(response.getheaders()), response.read()
+ finally:
+ connection.close()
+
+
+def wire(server, request, chunks=None):
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ if chunks:
+ for chunk in chunks:
+ sock.sendall(chunk)
+ else:
+ sock.sendall(request)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ return response.status, dict(response.getheaders()), response.read()
+
+
+def header(method, key, size=0, condition=b''):
+ return (f'{method} /objects/{key} HTTP/1.1\r\nHost: localhost\r\n'
+ f'Content-Length: {size}\r\n'.encode() + condition + b'\r\n')
+
+
+def cli(server, commands, source=None, expected_code=0):
+ result = subprocess.run(['node', str(WORKBENCH / 'cli.mjs'), *([str(source)] if source else [])],
+ input=commands.replace('$URL', f'http://127.0.0.1:{server.port}'), text=True,
+ capture_output=True, timeout=30)
+ assert result.returncode == expected_code, (result.stdout, result.stderr)
+ return [json.loads(line) for line in result.stdout.splitlines()], result.stderr
+
+
+def check(binary, directory, editor=None):
+ storage = directory / 'objects'
+ checks, records = [], []
+ with serving(binary, storage) as server:
+ assert rpc(server, 'GET', 'absent')[0] == 404
+ payload = b'\x00\xffbinary\r\n\r\n' + bytes(range(256)) * 41
+ request = header('PUT', 'binary', len(payload), b'If-None-Match: *\r\n') + payload
+ status, headers, _ = wire(server, request, [request[:7], request[7:51], request[51:57], request[57:]])
+ assert status == 200 and headers['ETag'] == '"1"'
+ assert rpc(server, 'GET', 'binary')[2] == payload
+ checks.append('fragmented request and binary bytes round trip')
+ assert rpc(server, 'PUT', 'binary', b'new', 0)[0] == 412
+ assert rpc(server, 'PUT', 'binary', b'new', 1)[0] == 200
+ assert rpc(server, 'PUT', 'binary', b'stale', 1)[0] == 412
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('conditional create and stale revision preserve committed bytes')
+
+ with (storage / '.writer.lock').open('r+b') as lock:
+ fcntl.lockf(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ assert rpc(server, 'PUT', 'binary', b'blocked', 2)[0] == 503
+ fcntl.lockf(lock, fcntl.LOCK_UN)
+ broken = storage / 'obj-broken'
+ broken.write_bytes(b'incomplete')
+ assert rpc(server, 'GET', 'broken')[0] == 500
+ assert rpc(server, 'PUT', 'broken', b'failure', 0)[0] == 500
+ assert broken.read_bytes() == b'incomplete'
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('writer contention and invalid extent fail without overwriting data')
+
+ with serving(binary, storage) as second_writer:
+ with ThreadPoolExecutor(max_workers=2) as pool:
+ tasks = [pool.submit(rpc, target, 'PUT', 'race', value, 0)
+ for target, value in [(server, b'first'), (second_writer, b'second')]]
+ statuses = [task.result()[0] for task in tasks]
+ assert statuses.count(200) == 1 and all(status in [200, 412, 503] for status in statuses)
+ status, headers, body = rpc(server, 'GET', 'race')
+ assert status == 200 and headers['ETag'] == '"1"' and body in [b'first', b'second']
+ records.append(second_writer.stats)
+ checks.append('two native writers cannot both create the same expected revision')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'incomplete', 100, b'If-None-Match: *\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ sock.close()
+ assert rpc(server, 'GET', 'incomplete')[0] == 404
+ checks.append('incomplete request never commits and releases its allocation')
+
+ # Force genuine partial socket sends. A write on another connection must
+ # not alter the immutable file whose bytes are still being transmitted.
+ large = bytes(range(256)) * 4096
+ assert rpc(server, 'PUT', 'large', large, 0)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.getheader('ETag') == '"1"'
+ assert response.read(17) == large[:17]
+ assert rpc(server, 'PUT', 'large', b'changed', 1)[0] == 200
+ assert response.read() == large[17:]
+ sock.close()
+ assert rpc(server, 'GET', 'large')[2] == b'changed'
+ checks.append('borrowed read remains the same snapshot during another commit')
+
+ assert rpc(server, 'PUT', 'large', large, 2)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ assert sock.recv(1)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ sock.close()
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('receiver reset aborts an outstanding borrowed transfer')
+
+ assert wire(server, header('PUT', 'too_large', OBJECT_LIMIT + 1, b'If-None-Match: *\r\n'))[0] == 413
+ malformed = [
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nContent-Length: 1\r\nContent-Length: 1\r\nIf-None-Match: *\r\n\r\nx',
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n',
+ b'GET /objects/bad HTTP/1.1\r\nHost: x\x00hidden\r\n\r\n',
+ ]
+ for request in malformed:
+ assert wire(server, request)[0] == 400
+ assert rpc(server, 'GET', 'bad')[0] == 404
+ checks.append('unsupported framing and oversized payload are rejected before effects')
+
+ # Existing authoring path: define, manipulate, save remotely, reconstruct
+ # in a fresh runtime. No fabricated project fixture or mock storage.
+ source = WORKBENCH / 'examples' / 'direct.pure'
+ saved = directory / 'restored.json'
+ lines, _ = cli(server, 'point drag down 80 180\npoint drag move 210 210\npoint drag up 210 210\n'
+ 'connect $URL authored\npush 0\nquit\n', source)
+ snapshots = [line for line in lines if 'states' in line]
+ assert snapshots
+ expected_states = snapshots[-1]['states']
+ assert expected_states['x'] == 210 and expected_states['y'] == 190 and expected_states['dragging'] == 0
+ lines, _ = cli(server, f'connect $URL authored\npull\nsave-project {saved}\nquit\n')
+ assert [line for line in lines if 'states' in line][-1]['states'] == expected_states
+ document = json.loads(saved.read_text())
+ assert document['version'] == 2 and document['source'] == source.read_text()
+ lines, error = cli(server, 'connect $URL authored\npush 0\nquit\n', source, 1)
+ assert '412' in error
+ checks.append('existing workbench manipulation restores in a fresh runtime and reports conflict')
+
+ assert rpc(server, 'PUT', 'invalid_project', b'{"format":"pure-workbench","version":2,"source":"state x=1","states":[]}', 0)[0] == 200
+ lines, error = cli(server, 'show\nconnect $URL invalid_project\npull\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and error
+ lines, error = cli(server, 'point drag down 90 170\nconnect $URL authored\npull\npush\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and states[-1]['dragging'] == 1
+ assert len(error.strip().splitlines()) == 2
+ checks.append('invalid or non-idle restore preserves local state and does not adopt remote revision')
+
+ assert rpc(server, 'PUT', 'wide_revision', rpc_bytes(saved), 0)[0] == 200
+ wide = storage / 'obj-wide_revision'
+ raw = wide.read_bytes()
+ wide.write_bytes(raw[:8] + struct.pack('<Q', 9007199254740993) + raw[16:])
+ lines, _ = cli(server, 'connect $URL wide_revision\npull\npush\nquit\n')
+ revisions = [line['revision'] for line in lines if 'remote' in line and 'revision' in line]
+ assert revisions == ['9007199254740993', '9007199254740994']
+ checks.append('revision above JavaScript safe integer round trips without numeric coercion')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'unread_ack', 4, b'If-None-Match: *\r\n') + b'done')
+ try:
+ deadline = time.monotonic() + 3
+ while True:
+ committed = storage / 'obj-unread_ack'
+ if committed.exists():
+ assert committed.read_bytes()[24:] == b'done'
+ break
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ finally:
+ sock.close() # Client never consumes the successful response.
+ assert rpc(server, 'PUT', 'unread_ack', b'again', 0)[0] == 412
+ assert rpc(server, 'GET', 'unread_ack')[2] == b'done'
+ checks.append('unread acknowledgment does not undo commit or permit a stale retry')
+
+ # A disconnect after commit can hide the ACK; retries remain conditional.
+ assert rpc(server, 'PUT', 'empty', b'', 0)[0] == 200
+ assert rpc(server, 'GET', 'empty')[2] == b''
+ checks.append('empty body has a valid lifetime and stored revision')
+ records.append(server.stats)
+
+ with serving(binary, storage) as restarted:
+ assert rpc(restarted, 'GET', 'binary')[2] == b'new'
+ assert rpc(restarted, 'GET', 'authored')[2] == rpc_bytes(saved)
+ checks.append('committed authoring state survives process restart')
+ records.append(restarted.stats)
+
+ # Fixed small payload budget is an admission test, not a throughput workload.
+ with serving(binary, storage, budget=1024 * 1024, timeout=1200) as limited:
+ sock = socket.create_connection(('127.0.0.1', limited.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200
+ assert response.read(1) == large[:1]
+ status, headers, _ = rpc(limited, 'GET', 'large')
+ assert status == 503 and headers['X-Pure-Error'] == 'payload_budget'
+ # Leave the first receiver stalled until the absolute connection deadline.
+ time.sleep(1.4)
+ assert rpc(limited, 'GET', 'binary')[2] == b'new'
+ response.close()
+ sock.close()
+ checks.append('slow consumer retains its lease; budget rejects another; deadline releases it')
+
+ idle = [socket.create_connection(('127.0.0.1', limited.port), timeout=8) for _ in range(8)]
+ try:
+ for s in idle:
+ s.sendall(b'G')
+ for s in idle:
+ assert s.recv(1) == b''
+ finally:
+ for s in idle:
+ s.close()
+ assert rpc(limited, 'GET', 'binary')[0] == 200
+ checks.append('connection slots stay bounded and recover after header deadlines')
+ assert limited.stats['budget_rejections'] >= 1 and limited.stats['expired'] >= 9
+ records.append(limited.stats)
+ prepared = authored_connections(binary, directory, storage, records, checks)
+ fields = field_connections(binary, directory, storage, records, checks)
+ edits = check_edits(editor, binary, ROOT, directory, serving, rpc, header, records, checks) if editor else None
+ return {'kind': 'prepared-connection-correctness-not-performance', 'checks': checks,
+ 'prepared_connections': prepared,
+ 'field_connections': fields,
+ 'document_edits': edits,
+ 'server_runs': records, 'storage': server.ready['storage']}
+
+
+def authored_connections(binary, directory, storage, records, checks):
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); }'
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); }'
+
+ def author(name, source):
+ path = directory / name
+ path.write_text(source)
+ return path
+
+ def explain(path):
+ return json.loads(subprocess.check_output([str(binary), '--check-program', str(path)], text=True))
+
+ with serving(binary, storage) as writer:
+ assert rpc(writer, 'PUT', 'short_parent', bytes(range(48)), 0)[0] == 200
+ assert rpc(writer, 'PUT', 'short_unused', bytes(range(80)), 0)[0] == 200
+ records.append(writer.stats)
+ excerpt = ROOT / 'examples/excerpt.pure'
+ prepared = {'excerpt': explain(excerpt)}
+ assert prepared['excerpt']['read'] == {
+ 'to_end': False, 'offset': 32, 'length': 16, 'minimum_source_bytes': 80}
+ with serving(binary, storage, budget=16, program=excerpt) as selected:
+ status, headers, body = rpc(selected, 'GET', 'large')
+ assert status == 200 and body == bytes(range(32, 48)) and headers['ETag'] == '"3"'
+ # Final [32,48) fits, but the authored parent [16,80) does not.
+ assert rpc(selected, 'GET', 'short_parent')[0] == 413
+ assert rpc(selected, 'GET', 'missing')[0] == 404
+ assert selected.stats['peak_retained_payload_bytes'] == 16
+ records.append(selected.stats)
+ checks.append('authored nested read maps only final demand while preserving parent bounds and revision')
+
+ unused = author('unused.pure', 'on get { let o = store.read(request.key); '
+ 'let unused = range(o.body, 0, 96); let body = range(o.body, 32, 16); reply(o, body); } ' + put)
+ with serving(binary, storage, budget=16, program=unused) as guarded:
+ assert rpc(guarded, 'GET', 'short_unused')[0] == 413
+ assert rpc(guarded, 'GET', 'large')[2] == bytes(range(32, 48))
+ records.append(guarded.stats)
+ checks.append('unused checked view still fails even when response range would be valid')
+
+ select_write = author('write.pure', get + ' on put { let a = range(request.body, 2, 10); '
+ 'let b = range(a, 3, 4); let alias = b; '
+ 'let saved = store.write(request.key, request.revision, alias); reply(saved, b); }')
+ prepared['write'] = explain(select_write)
+ with serving(binary, storage, program=select_write) as writer:
+ status, headers, body = rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'GET', 'selected')[2] == b'5678'
+ assert rpc(writer, 'PUT', 'selected', b'012345678', 1)[0] == 413
+ status, headers, body = rpc(writer, 'GET', 'selected')
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)[0] == 412
+ records.append(writer.stats)
+ checks.append('authored write and reply share selected input; invalid parent prevents the storage effect')
+
+ metadata = author('metadata.pure', 'on get { let o = store.read(request.key); reply(o); } ' + put)
+ with serving(binary, storage, budget=1, program=metadata) as meta:
+ status, headers, body = rpc(meta, 'GET', 'large')
+ assert status == 200 and headers['ETag'] == '"3"' and body == b''
+ assert rpc(meta, 'GET', 'absent')[0] == 404
+ assert rpc(meta, 'GET', 'broken')[0] == 500
+ assert meta.stats['peak_retained_payload_bytes'] == 0
+ records.append(meta.stats)
+ checks.append('body-free response preserves read existence and malformed-object errors')
+
+ echo = author('echo.pure', get + ' on put { let body = request.body; '
+ 'let saved = store.write(request.key, request.revision, body); reply(saved, body); }')
+ payload = bytes(range(256)) * 4096
+ with serving(binary, storage, budget=len(payload), program=echo) as echoed:
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == payload[:1]
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ assert response.read() == payload[1:]
+ response.close()
+ assert rpc(echoed, 'GET', 'binary')[2] == b'new'
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo_abort', len(payload), b'If-None-Match: *\r\n') + payload)
+ assert sock.recv(1)
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ deadline = time.monotonic() + 3
+ while rpc(echoed, 'GET', 'binary')[0] == 503:
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ assert rpc(echoed, 'GET', 'echo_abort')[2] == payload
+ records.append(echoed.stats)
+ checks.append('input-backed response survives partial send and releases on finish or abort without undoing commit')
+
+ bad = author('invalid.pure', get + get + put)
+ untouched = directory / 'must_not_exist'
+ rejected = subprocess.run([str(binary), '--program', str(bad), '--store', str(untouched)],
+ capture_output=True, text=True, timeout=10)
+ assert rejected.returncode == 2 and 'duplicate handler' in rejected.stderr and not untouched.exists()
+ checks.append('invalid authored program fails preparation before creating storage or accepting requests')
+ return prepared
+
+
+def field_connections(binary, directory, storage, records, checks):
+ program = ROOT / 'examples/selection.pure'
+ plans = {'selection': json.loads(subprocess.check_output(
+ [str(binary), '--check-program', str(program)], text=True))}
+ assert plans['selection']['runtime_view_steps'] == 1
+ assert plans['selection']['steps'][0] == {
+ 'source_step': 0, 'source': {'offset': 8, 'length': 0, 'to_end': True},
+ 'offset': {'value': 0, 'from_u32le': True}, 'length': {'value': 4, 'from_u32le': True}}
+ document = '처음🙂 Pure는 필드를 연결한다.\n끝'
+ document_file = directory / 'document.txt'
+ document_file.write_bytes(document.encode('utf-8'))
+ with serving(binary, storage, program=program) as selected:
+ command = [sys.executable, str(ROOT / 'examples/select-text.py'), str(document_file),
+ '--key', 'text_selection', '--start', '2', '--end', '12', '--url', f'http://127.0.0.1:{selected.port}']
+ result = subprocess.run(command, capture_output=True, text=True, timeout=15)
+ assert result.returncode == 0, (result.stdout, result.stderr)
+ expected = document[2:12].encode('utf-8')
+ assert json.loads(result.stdout) == {'revision': '1', 'selected': document[2:12], 'stored_bytes': len(expected)}
+ assert rpc(selected, 'GET', 'text_selection')[2] == expected
+ checks.append('text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes')
+
+ # Validation precedes the write: even a stale header cannot expose or
+ # commit partial input, and prior content/revision survive all failures.
+ invalid = [b'\0' * n for n in range(8)] + [
+ struct.pack('<II', 0xffffffff, 0) + b'abc',
+ struct.pack('<II', 0, 0xffffffff) + b'abc',
+ struct.pack('<II', 2, 2) + b'abc',
+ struct.pack('<II', 4, 0) + b'abc']
+ for payload in invalid:
+ assert rpc(selected, 'PUT', 'text_selection', payload, 1)[0] == 413
+ status, headers, body = rpc(selected, 'GET', 'text_selection')
+ assert status == 200 and headers['ETag'] == '"1"' and body == expected
+ for key, payload in [('selection_empty', struct.pack('<II', 0, 0)),
+ ('selection_end', struct.pack('<II', 3, 0) + b'abc')]:
+ assert rpc(selected, 'PUT', key, payload, 0)[0] == 200
+ assert rpc(selected, 'GET', key)[2] == b''
+ assert rpc(selected, 'PUT', 'text_selection', struct.pack('<II', 0, 3) + b'abc', 0)[0] == 412
+ checks.append('truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid')
+ records.append(selected.stats)
+
+ declaration = 'layout E { tag: bytes[3]; count: u32le; start: u32le; document: bytes; } '
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); } '
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); } '
+ reordered = directory / 'reordered.pure'
+ reordered.write_text(declaration + get + 'on put { let e = view(E, request.body); let alias = e; '
+ 'let part = range(alias.document, alias.start, alias.count); let again = part; '
+ 'let s = store.write(request.key, request.revision, again); reply(s, part); }')
+ plans['reordered'] = json.loads(subprocess.check_output([str(binary), '--check-program', str(reordered)], text=True))
+ assert plans['reordered']['runtime_view_steps'] == 1
+ with serving(binary, storage, program=reordered) as moved:
+ status, headers, body = rpc(moved, 'PUT', 'reordered', b'tag' + struct.pack('<II', 4, 2) + b'abcdefgh', 0)
+ assert status == 200 and body == b'cdef' and headers['ETag'] == '"1"'
+ assert rpc(moved, 'GET', 'reordered')[2] == b'cdef'
+ records.append(moved.stats)
+ checks.append('changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps')
+
+ unused = directory / 'unused-dynamic.pure'
+ unused.write_text(declaration + get + 'on put { let e = view(E, request.body); '
+ 'let unused = range(e.document, e.start, e.count); '
+ 'let s = store.write(request.key, request.revision, e.document); reply(s); }')
+ with serving(binary, storage, program=unused) as guarded:
+ assert rpc(guarded, 'PUT', 'unused_dynamic', b'tag' + struct.pack('<II', 4, 2) + b'abc', 0)[0] == 413
+ assert rpc(guarded, 'GET', 'unused_dynamic')[0] == 404
+ assert rpc(guarded, 'PUT', 'unused_dynamic', b'tag' + struct.pack('<II', 1, 1) + b'abc', 0)[0] == 200
+ assert rpc(guarded, 'GET', 'unused_dynamic')[2] == b'abc'
+ records.append(guarded.stats)
+ checks.append('unused dynamic field selection retains its validation before the write effect')
+
+ field_get = directory / 'field-get.pure'
+ field_get.write_text(declaration + 'on get { let o = store.read(request.key); '
+ 'let e = view(E, o.body); reply(o, e.document); } ' + put)
+ plans['field_get'] = json.loads(subprocess.check_output([str(binary), '--check-program', str(field_get)], text=True))
+ tail = '다른 길이의 문서'.encode('utf-8')
+ with serving(binary, storage, program=field_get) as writer:
+ assert rpc(writer, 'PUT', 'tail', b'tag' + struct.pack('<II', 0, 0) + tail, 0)[0] == 200
+ assert rpc(writer, 'PUT', 'bad_layout', b'short', 0)[0] == 200
+ assert rpc(writer, 'PUT', 'empty_tail', b'tag' + struct.pack('<II', 0, 0), 0)[0] == 200
+ records.append(writer.stats)
+ with serving(binary, storage, budget=len(tail), program=field_get) as reader:
+ assert rpc(reader, 'GET', 'tail')[2] == tail
+ assert rpc(reader, 'GET', 'empty_tail')[2] == b''
+ assert rpc(reader, 'GET', 'bad_layout')[0] == 413
+ assert reader.stats['peak_retained_payload_bytes'] == len(tail)
+ records.append(reader.stats)
+ checks.append('named variable tail reads use the same file version and charge only the selected suffix')
+
+ document_bytes = bytes(range(256)) * 4096
+ payload = struct.pack('<II', 16, len(document_bytes) - 32) + document_bytes
+ with serving(binary, storage, budget=len(payload), program=program) as slow:
+ with socket.create_connection(('127.0.0.1', slow.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'dynamic_slow', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == document_bytes[16:17]
+ assert rpc(slow, 'GET', 'binary')[0] == 503
+ assert response.read() == document_bytes[17:-16]
+ response.close()
+ assert rpc(slow, 'GET', 'binary')[2] == b'new'
+ assert rpc(slow, 'GET', 'dynamic_slow')[2] == document_bytes[16:-16]
+ assert slow.stats['peak_retained_payload_bytes'] == len(payload)
+ records.append(slow.stats)
+ checks.append('data-dependent response keeps and charges the original input through partial transmission')
+ return plans
+
+
+def rpc_bytes(path):
+ # CLI export is pretty JSON; wire export is compact JSON with the same model.
+ return json.dumps(json.loads(path.read_text()), ensure_ascii=False, separators=(',', ':')).encode()
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path, default=ROOT / 'build/pure-connections')
+ parser.add_argument('--output', type=Path)
+ parser.add_argument('--runtime-test', type=Path)
+ parser.add_argument('--splice-test', type=Path)
+ parser.add_argument('--editor', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ binary = args.server.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-connections-check-') as temporary:
+ result = check(binary, Path(temporary), args.editor.resolve() if args.editor else None)
+ if args.runtime_test:
+ runtime_test = args.runtime_test.resolve()
+ tested = subprocess.run([str(runtime_test)], cwd=ROOT, capture_output=True, text=True, timeout=30)
+ assert tested.returncode == 0, (tested.stdout, tested.stderr)
+ result['execution_core'] = json.loads(tested.stdout)
+ result['execution_core_test_sha256'] = hashlib.sha256(runtime_test.read_bytes()).hexdigest()
+ if args.splice_test:
+ splice_test = args.splice_test.resolve()
+ tested = subprocess.run([str(splice_test)], cwd=ROOT, capture_output=True, text=True, timeout=30)
+ assert tested.returncode == 0, (tested.stdout, tested.stderr)
+ result['document_edit_units'] = json.loads(tested.stdout)
+ result['document_edit_test_sha256'] = hashlib.sha256(splice_test.read_bytes()).hexdigest()
+ if args.editor:
+ result['editor_sha256'] = hashlib.sha256(args.editor.resolve().read_bytes()).hexdigest()
+ result['binary_sha256'] = hashlib.sha256(binary.read_bytes()).hexdigest()
+ result['environment'] = {'platform': platform.platform(), 'machine': platform.machine(),
+ 'python': platform.python_version(), 'node': subprocess.check_output(['node', '--version'], text=True).strip()}
+ result['source_sha256'] = {str(path.relative_to(ROOT.parent.parent)): hashlib.sha256(path.read_bytes()).hexdigest()
+ for path in [*(ROOT / name for name in ('flow.c', 'flow.h', 'store.c', 'store.h', 'program.c', 'program.h',
+ 'runtime.c', 'runtime.h', 'result.h', 'evaluate.c', 'store-port.c', 'store-port.h', 'test-runtime.c',
+ 'server.c', 'check.py', 'check_edits.py', 'edit.c', 'test-splice.c',
+ 'test-flow.c', 'test-program.c', 'test-fields.c', 'Makefile',
+ 'core-layout.c', 'check_core.py', 'core-budget.json', 'examples/editor.pure',
+ 'examples/storage.pure', 'examples/excerpt.pure', 'examples/selection.pure', 'examples/select-text.py')),
+ *(WORKBENCH / name for name in ('remote.mjs', 'cli.mjs', 'web/core.wasm', 'web/runtime.mjs',
+ 'web/compiler.mjs', 'web/project.mjs', 'examples/direct.pure'))]}
+ output = json.dumps(result, ensure_ascii=False, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check_core.py b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check_core.py
new file mode 100644
index 0000000..321896e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check_core.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+"""Fail when the selected execution core grows past its reviewed cost boundary.
+
+This is a release-build structural check using GNU-compatible ar/nm/size. Run it
+separately from correctness/sanitizer tests; instrumented objects have other costs.
+"""
+import argparse
+import hashlib
+import json
+from pathlib import Path
+import platform
+import subprocess
+
+ROOT = Path(__file__).resolve().parent
+
+
+def run(*args):
+ return subprocess.check_output([str(arg) for arg in args], text=True)
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--archive', type=Path, required=True)
+ parser.add_argument('--layout', type=Path, required=True)
+ parser.add_argument('--budget', type=Path, default=ROOT / 'core-budget.json')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ budget = json.loads(args.budget.read_text())
+ archive = args.archive.resolve()
+ members = run('ar', 't', archive).splitlines()
+ layout = json.loads(run(args.layout.resolve()))
+ size_output = run('size', archive)
+ rows = [line.split() for line in size_output.splitlines() if line.split() and line.split()[0].isdigit()]
+ if len(rows) != len(members):
+ parser.error('unsupported size output; no footprint claim was made')
+ sizes = {name: sum(int(row[i]) for row in rows) for i, name in enumerate(('text', 'data', 'bss'))}
+ defined = {line.split()[-1] for line in run('nm', '-g', '--defined-only', archive).splitlines()
+ if len(line.split()) >= 3}
+ undefined = {line.split()[-1] for line in run('nm', '-u', archive).splitlines()
+ if len(line.split()) == 2 and line.split()[0] == 'U'}
+ external = sorted(undefined - defined)
+ failures = []
+ if sorted(members) != sorted(budget['archive_members']):
+ failures.append('unexpected archive members')
+ for name, value in sizes.items():
+ if value > budget[f'max_{name}_bytes']:
+ failures.append(f'{name}: {value} > {budget[f"max_{name}_bytes"]}')
+ for name, maximum in budget['layout_max_bytes'].items():
+ if layout[name] > maximum:
+ failures.append(f'{name}: {layout[name]} > {maximum}')
+ extra = set(external) - set(budget['external_symbols_allowed'])
+ if extra:
+ failures.append(f'unexpected dependencies: {sorted(extra)}')
+ result = {'passed': not failures, 'failures': failures, 'budget': budget,
+ 'layout': layout, 'sections': sizes, 'members': members,
+ 'external_symbols': external, 'size_output': size_output,
+ 'archive_sha256': hashlib.sha256(archive.read_bytes()).hexdigest(),
+ 'layout_binary_sha256': hashlib.sha256(args.layout.resolve().read_bytes()).hexdigest(),
+ 'budget_sha256': hashlib.sha256(args.budget.read_bytes()).hexdigest(),
+ 'platform': platform.platform(), 'size_tool': run('size', '--version').splitlines()[0]}
+ output = json.dumps(result, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+ if failures:
+ raise SystemExit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check_edits.py b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check_edits.py
new file mode 100644
index 0000000..1a6dc53
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/check_edits.py
@@ -0,0 +1,108 @@
+"""Real native automation and HTTP clients editing the same authored document."""
+from concurrent.futures import ThreadPoolExecutor
+import json
+import socket
+import struct
+import subprocess
+
+
+def check_edits(editor, binary, root, directory, serving, rpc, header, records, checks):
+ storage = directory / 'edited-objects'
+ program = root / 'examples/editor.pure'
+ file = directory / 'insertion.bin'
+
+ def local(*args, body=None, code=0, source=program, budget=None):
+ if body is not None:
+ file.write_bytes(body)
+ args = (*args, str(file))
+ command = [str(editor), '--program', str(source), '--store', str(storage)]
+ if budget is not None:
+ command += ['--budget', str(budget)]
+ result = subprocess.run(command + [str(arg) for arg in args], capture_output=True, timeout=20)
+ assert result.returncode == code, (command, args, result.stdout, result.stderr)
+ return result
+
+ initial = 'Pure에서 안녕 🌏\n'.encode()
+ created = local('edit', 'note', 0, 0, 0, body=initial)
+ assert json.loads(created.stdout)['revision'] == '1'
+ start = initial.index('안녕'.encode())
+ inserted = '반가워'.encode()
+ expected = initial[:start] + inserted + initial[start + len('안녕'.encode()):]
+ local('edit', 'note', 1, start, len('안녕'.encode()), body=inserted)
+ shown = local('show', 'note')
+ assert shown.stdout == expected and json.loads(shown.stderr)['revision'] == '2'
+ checks.append('native authored byte edit and fresh native process restore UTF-8 content')
+ stale = local('edit', 'note', 1, 0, 0, body=b'bad', code=3)
+ assert json.loads(stale.stderr) == {'error': 'conflict', 'revision': '2'}
+ local('edit', 'note', 2, 0xffffffff, 0, body=b'bad', code=2)
+ assert local('show', 'note').stdout == expected
+ checks.append('native stale revision and invalid byte position preserve the committed document')
+
+ reordered = directory / 'edit-reordered.pure'
+ reordered.write_text('layout E { tag: bytes[1]; remove: u32le; start: u32le; body: bytes; } '
+ 'on get { let o = store.read(request.key); reply(o, o.body); } '
+ 'on put { let e = view(E, request.body); '
+ 'let s = store.splice(request.key, request.revision, e.start, e.remove, e.body); reply(s, e.body); }')
+ local('edit', 'note', 2, len(expected), 0, body=b'!', source=reordered)
+ expected += b'!'
+ assert local('show', 'note', source=reordered).stdout == expected
+ checks.append('native convenience editor derives unaligned reordered field positions from the authored program')
+
+ custom = directory / 'edit-custom.pure'
+ custom.write_text('on get { let o = store.read(request.key); reply(o, o.body); } '
+ 'on put { let s = store.splice(request.key, request.revision, 0, 0, request.body); reply(s); }')
+ local('edit', 'custom', 0, 0, 0, body=b'ignored', source=custom, code=2)
+ applied = local('apply', 'custom', 0, body=b'custom input', source=custom)
+ assert json.loads(applied.stdout) == {'revision': '1', 'reply_bytes': 0}
+ assert local('show', 'custom', source=custom).stdout == b'custom input'
+ checks.append('raw native apply runs another authored input contract without changing the executor')
+
+ with serving(binary, storage, program=program) as server:
+ assert rpc(server, 'GET', 'note')[2] == expected
+ status, headers, body = rpc(server, 'PUT', 'note', struct.pack('<II', len(expected), 0) + b'?', 3)
+ assert status == 200 and headers['ETag'] == '"4"' and body == b'?'
+ expected += b'?'
+ assert local('show', 'note').stdout == expected
+ local('edit', 'note', 4, 0, 4, body=b'PURE')
+ expected = b'PURE' + expected[4:]
+ assert rpc(server, 'PUT', 'note', struct.pack('<II', 0, 0) + b'stale', 4)[0] == 412
+ assert rpc(server, 'GET', 'note')[2] == expected
+ checks.append('native CLI and external HTTP share revisions and the same authored storage effect in both directions')
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'note', 12, b'If-Match: "5"\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ assert rpc(server, 'PUT', 'note', b'short', 5)[0] == 413
+ assert rpc(server, 'PUT', 'note', struct.pack('<II', 0xffffffff, 0), 5)[0] == 413
+ assert rpc(server, 'GET', 'note')[2] == expected
+ checks.append('partial or invalid edit input never modifies the stored document')
+ with serving(binary, storage, program=program) as other:
+ with ThreadPoolExecutor(max_workers=2) as pool:
+ tasks = [pool.submit(rpc, target, 'PUT', 'note', struct.pack('<II', 0, 0) + value, 5)
+ for target, value in ((server, b'A'), (other, b'B'))]
+ statuses = [task.result()[0] for task in tasks]
+ assert statuses.count(200) == 1 and all(status in (200, 412, 503) for status in statuses)
+ status, headers, body = rpc(server, 'GET', 'note')
+ assert status == 200 and headers['ETag'] == '"6"'
+ assert body == (b'A' if statuses[0] == 200 else b'B') + expected
+ records.append(other.stats)
+ checks.append('two processes cannot both splice the same expected document revision')
+ records.append(server.stats)
+
+ # This tests retained input size for a real large edit, not throughput.
+ large = bytes(range(256)) * 4096
+ local('edit', 'large', 0, 0, 0, body=large)
+ local('edit', 'large', 1, 524287, 3, body=b'XYZ', budget=11)
+ expected_large = large[:524287] + b'XYZ' + large[524290:]
+ assert local('show', 'large').stdout == expected_large
+ with serving(binary, storage, program=program, budget=11) as bounded:
+ status, headers, body = rpc(bounded, 'PUT', 'large', struct.pack('<II', 524287, 3) + b'abc', 2)
+ assert status == 200 and headers['ETag'] == '"3"' and body == b'abc'
+ assert rpc(bounded, 'PUT', 'large', struct.pack('<II', 0, 0) + b'abcd', 3)[0] == 503
+ assert bounded.stats['peak_retained_payload_bytes'] == 11
+ records.append(bounded.stats)
+ assert local('show', 'large').stdout == large[:524287] + b'abc' + large[524290:]
+ checks.append('1 MiB document changes with 11 input credits; larger input is rejected before an effect')
+ return {'large_document_bytes': len(large), 'small_edit_input_bytes': 11,
+ 'storage_rewrites_full_extent': True, 'storage_scratch_bytes': 4096,
+ 'kind': 'correctness-and-admission-not-total-memory-or-performance'}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/core-budget.json b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/core-budget.json
new file mode 100644
index 0000000..82d830b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/core-budget.json
@@ -0,0 +1,15 @@
+{
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": ["runtime.o", "evaluate.o"],
+ "external_symbols_allowed": ["memcpy", "memmove", "memset", "strlen"],
+ "scope": "Release object sections and C bookkeeping, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/core-layout.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/core-layout.c
new file mode 100644
index 0000000..6687be7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/core-layout.c
@@ -0,0 +1,11 @@
+#include "runtime.h"
+#include <stdio.h>
+
+/* Host-side measurement tool; never linked into libpure-execution.a. */
+int main(void) {
+ printf("{\"domain_bytes\":%zu,\"work_slot_bytes\":%zu,\"ticket_bytes\":%zu,"
+ "\"prepared_program_bytes\":%zu,\"pointer_bytes\":%zu}\n",
+ sizeof(PureRuntime), sizeof(PureWork), sizeof(PureTicket),
+ sizeof(PureProgram), sizeof(void *));
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/edit.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/edit.c
new file mode 100644
index 0000000..4daad14
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/edit.c
@@ -0,0 +1,153 @@
+#define _POSIX_C_SOURCE 200809L
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Native automation entry for the same prepared document program as the
+ * network adapter. No socket or body serialization in the local execution. */
+static bool number(const char *text, uint64_t limit, uint64_t *out) {
+ if (!*text) return false;
+ uint64_t value = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > limit || value > (limit - digit) / 10) return false;
+ value = value * 10 + digit;
+ }
+ *out = value;
+ return true;
+}
+
+static const char *message(PureResult status) {
+ switch (status) {
+ case PURE_OK: return "ok";
+ case PURE_NOT_FOUND: return "not_found";
+ case PURE_CONFLICT: return "conflict";
+ case PURE_BUSY: return "busy";
+ case PURE_BUDGET: return "payload_budget";
+ case PURE_LIMIT: return "limit";
+ case PURE_UNCERTAIN: return "durability_unknown";
+ case PURE_DENIED: return "denied";
+ case PURE_ALLOCATION: return "allocation";
+ case PURE_INVALID: return "invalid";
+ default: return "failed";
+ }
+}
+
+static void put32(unsigned char *to, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) to[i] = (unsigned char)(value >> (8 * i));
+}
+
+/* The convenience command fills the program's two numeric splice arguments
+ * and its trailing insertion bytes. A more general input uses apply. */
+static bool edit_layout(const PureProgram *p, size_t *prefix) {
+ if (!p->splice || !p->write.to_end || p->write_step || p->input_steps ||
+ !p->splice_offset.from_u32le || !p->splice_remove.from_u32le) return false;
+ size_t start = p->splice_offset.value, remove = p->splice_remove.value;
+ *prefix = p->write.offset;
+ if (*prefix > PURE_OBJECT_LIMIT || p->input_required > *prefix || start > *prefix ||
+ remove > *prefix || *prefix - start < 4 || *prefix - remove < 4) return false;
+ return start < remove ? remove - start >= 4 : start - remove >= 4;
+}
+
+int main(int argc, char **argv) {
+ const char *program_path = NULL, *store_path = NULL;
+ size_t budget = 4u * 1024u * 1024u;
+ int at = 1;
+ for (; at + 1 < argc && !strncmp(argv[at], "--", 2); at += 2) {
+ uint64_t value;
+ if (!strcmp(argv[at], "--program")) program_path = argv[at + 1];
+ else if (!strcmp(argv[at], "--store")) store_path = argv[at + 1];
+ else if (!strcmp(argv[at], "--budget") && number(argv[at + 1], SIZE_MAX, &value)) budget = (size_t)value;
+ else goto usage;
+ }
+ if (!program_path || !store_path || at >= argc) goto usage;
+ bool show = !strcmp(argv[at], "show"), edit = !strcmp(argv[at], "edit");
+ if ((!show && !edit && strcmp(argv[at], "apply")) ||
+ argc - at != (show ? 2 : edit ? 6 : 4)) goto usage;
+ uint64_t expected = 0, offset = 0, remove = 0;
+ if (!show && !number(argv[at + 2], INT64_MAX, &expected)) goto usage;
+ if (edit && (!number(argv[at + 3], UINT32_MAX, &offset) || !number(argv[at + 4], UINT32_MAX, &remove))) goto usage;
+ PureProgram program;
+ char error[160];
+ if (!pure_program_load(program_path, &program, error, sizeof(error))) {
+ fprintf(stderr, "Program: %s\n", error); return 2;
+ }
+ size_t prefix = 0;
+ if (edit && !edit_layout(&program, &prefix)) {
+ fputs("edit requires two distinct u32le splice fields and trailing insertion bytes; use apply for a custom input\n", stderr);
+ return 2;
+ }
+ FILE *file = NULL;
+ size_t length = 0;
+ if (!show) {
+ file = fopen(argv[at + (edit ? 5 : 3)], "rb");
+ if (!file) { perror("input"); return 2; }
+ long bytes;
+ if (fseek(file, 0, SEEK_END) || (bytes = ftell(file)) < 0 ||
+ (uintmax_t)bytes > PURE_OBJECT_LIMIT - prefix || fseek(file, 0, SEEK_SET)) {
+ fputs("input must be a seekable file within the request size limit\n", stderr);
+ fclose(file); return 2;
+ }
+ length = (size_t)bytes;
+ }
+ if (pure_store_init(store_path) != PURE_OK) {
+ if (file) fclose(file);
+ fputs("cannot initialize store\n", stderr); return 2;
+ }
+ PureRuntime runtime;
+ PureWork work[1];
+ if (!pure_runtime_init(&runtime, work, 1, &program, pure_store_host(store_path), budget)) {
+ if (file) fclose(file);
+ return 2;
+ }
+ PureTicket ticket;
+ PureResult admitted = pure_runtime_accept(&runtime, show ? PURE_INPUT_READ : PURE_INPUT_WRITE,
+ argv[at + 1], (int64_t)expected, prefix + length, &ticket);
+ if (admitted != PURE_OK) {
+ if (file) fclose(file);
+ fprintf(stderr, "%s\n", message(admitted)); return 2;
+ }
+ if (!show) {
+ unsigned char *input = pure_runtime_ingress(ticket, NULL);
+ if (prefix) memset(input, 0, prefix);
+ if (edit) {
+ put32(input + program.splice_offset.value, (uint32_t)offset);
+ put32(input + program.splice_remove.value, (uint32_t)remove);
+ }
+ bool valid = !length || fread(input + prefix, 1, length, file) == length;
+ if (fgetc(file) != EOF || ferror(file)) valid = false;
+ if (fclose(file)) valid = false;
+ if (!valid) {
+ pure_runtime_release(ticket);
+ fputs("input changed or could not be read; nothing was applied\n", stderr); return 2;
+ }
+ if (!pure_runtime_ready(ticket)) { pure_runtime_release(ticket); return 2; }
+ }
+ PureOutcome outcome;
+ while (!pure_runtime_result(ticket, &outcome)) {
+ if (!pure_runtime_step(&runtime)) { pure_runtime_release(ticket); return 2; }
+ }
+ int status = 0;
+ if (outcome.status != PURE_OK) {
+ fprintf(stderr, "{\"error\":\"%s\",\"revision\":\"%" PRId64 "\"}\n", message(outcome.status), outcome.revision);
+ status = outcome.status == PURE_CONFLICT ? 3 : 2;
+ } else if (show) {
+ if (outcome.body.size && fwrite(outcome.body.data, 1, outcome.body.size, stdout) != outcome.body.size) status = 2;
+ fprintf(stderr, "{\"revision\":\"%" PRId64 "\",\"bytes\":%zu}\n", outcome.revision, outcome.body.size);
+ } else {
+ if (printf("{\"revision\":\"%" PRId64 "\",\"reply_bytes\":%zu}\n", outcome.revision, outcome.body.size) < 0) status = 2;
+ }
+ if (fflush(stdout)) status = 2;
+ pure_runtime_release(ticket);
+ return status;
+usage:
+ fputs("pure-edit --program FILE --store DIRECTORY [--budget BYTES] show KEY\n"
+ "pure-edit --program FILE --store DIRECTORY [--budget BYTES] edit KEY REVISION BYTE_OFFSET REMOVE_BYTES INSERT_FILE\n"
+ "pure-edit --program FILE --store DIRECTORY [--budget BYTES] apply KEY REVISION INPUT_FILE\n"
+ "edit uses the prepared program's field locations; apply accepts its raw input bytes.\n", stderr);
+ return 2;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/evaluate.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/evaluate.c
new file mode 100644
index 0000000..88ffae7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/evaluate.c
@@ -0,0 +1,53 @@
+#include "program.h"
+#include <stdint.h>
+
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out) {
+ *out = (PureSpan){0};
+ if (region.offset > source.size) return false;
+ size_t length = region.to_end ? source.size - region.offset : region.length;
+ if (length > source.size - region.offset) return false;
+ *out = (PureSpan){length ? source.data + region.offset : NULL, length};
+ return true;
+}
+
+static bool index_read(PureIndex index, PureSpan source, size_t *out) {
+ if (!index.from_u32le) { *out = index.value; return true; }
+ if (index.value > source.size || 4 > source.size - index.value) return false;
+ const unsigned char *bytes = source.data + index.value;
+ *out = (size_t)bytes[0] | (size_t)bytes[1] << 8 | (size_t)bytes[2] << 16 | (size_t)bytes[3] << 24;
+ return true;
+}
+
+bool pure_program_splice(const PureProgram *p, PureSpan source, size_t *offset, size_t *remove) {
+ return p->splice && index_read(p->splice_offset, source, offset) &&
+ index_read(p->splice_remove, source, remove);
+}
+
+static bool resolve(PureRegion region, size_t step, PureSpan source,
+ const PureSpan *values, size_t count, PureSpan *out) {
+ if (!step) return pure_region_span(region, source, out);
+ if (step > count) return false;
+ *out = values[step - 1];
+ return true;
+}
+
+bool pure_program_input(const PureProgram *p, PureSpan source, PureSpan *write, PureSpan *reply) {
+ *write = (PureSpan){0};
+ *reply = (PureSpan){0};
+ if (source.size < p->input_required || p->input_steps > PURE_DYNAMIC_LIMIT) return false;
+ PureSpan values[PURE_DYNAMIC_LIMIT];
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ PureSpan parent;
+ size_t offset, length;
+ if (!resolve(step->source, step->source_step, source, values, i, &parent) ||
+ !index_read(step->offset, source, &offset) || !index_read(step->length, source, &length) ||
+ !pure_region_span((PureRegion){.offset = offset, .length = length}, parent, &values[i])) return false;
+ }
+ PureSpan stored, returned = {0};
+ if (!resolve(p->write, p->write_step, source, values, p->input_steps, &stored) ||
+ (p->reply_input && !resolve(p->reply, p->reply_step, source, values, p->input_steps, &returned))) return false;
+ *write = stored;
+ *reply = returned;
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/editor.pure b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/editor.pure
new file mode 100644
index 0000000..4de78bc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/editor.pure
@@ -0,0 +1,19 @@
+// A revision-checked byte edit. The input carries only the replacement.
+// UTF-8 cursor/grapheme positions are translated to byte ranges by the UI.
+layout Edit {
+ start: u32le;
+ remove: u32le;
+ insert: bytes;
+}
+
+on get {
+ let document = store.read(request.key);
+ reply(document, document.body);
+}
+
+on put {
+ let edit = view(Edit, request.body);
+ let saved = store.splice(request.key, request.revision,
+ edit.start, edit.remove, edit.insert);
+ reply(saved, edit.insert);
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/excerpt.pure b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/excerpt.pure
new file mode 100644
index 0000000..622f9bb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/excerpt.pure
@@ -0,0 +1,13 @@
+// Read bytes 32..47 of an object that must contain the complete 64-byte window.
+// Preparation keeps the size check for 16..79, and maps only 32..47 for reply.
+on get {
+ let object = store.read(request.key);
+ let window = range(object.body, 16, 64);
+ let excerpt = range(window, 16, 16);
+ reply(object, excerpt);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/select-text.py b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/select-text.py
new file mode 100644
index 0000000..ffaf80b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/select-text.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+"""Save a UTF-8 document selection through selection.pure (character indices)."""
+import argparse
+import http.client
+import json
+from pathlib import Path
+import re
+import struct
+from urllib.parse import urlsplit
+
+LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('file', type=Path)
+ parser.add_argument('--key', required=True)
+ parser.add_argument('--start', type=int, required=True, help='first Unicode code point, starting at 0')
+ parser.add_argument('--end', type=int, required=True, help='exclusive Unicode code point boundary')
+ parser.add_argument('--revision', type=int, default=0, help='0 creates; otherwise expected stored revision')
+ parser.add_argument('--url', default='http://127.0.0.1:8767')
+ args = parser.parse_args()
+ url = urlsplit(args.url)
+ try:
+ port = url.port or 80
+ except ValueError as error:
+ parser.error(str(error))
+ if (url.scheme != 'http' or url.hostname not in ['localhost', '127.0.0.1'] or
+ url.username is not None or url.password is not None or url.path not in ['', '/'] or
+ url.query or url.fragment):
+ parser.error('use a local HTTP server origin')
+ if not re.fullmatch(r'[A-Za-z0-9_-]{1,64}', args.key) or not 0 <= args.revision <= 2**63 - 1:
+ parser.error('invalid object key or revision')
+ try:
+ with args.file.open('rb') as source:
+ document = source.read(LIMIT - 8 + 1)
+ if len(document) > LIMIT - 8:
+ parser.error('document exceeds the prototype request limit')
+ text = document.decode('utf-8')
+ except (OSError, UnicodeError) as error:
+ parser.error(str(error))
+ if not 0 <= args.start <= args.end <= len(text):
+ parser.error('selection is outside the document')
+ start = len(text[:args.start].encode('utf-8'))
+ selected = text[args.start:args.end].encode('utf-8')
+ # The boundary layout is explicit; storage receives only selected bytes.
+ payload = struct.pack('<II', start, len(selected)) + document
+ headers = {'Content-Type': 'application/octet-stream'}
+ headers['If-None-Match' if args.revision == 0 else 'If-Match'] = (
+ '*' if args.revision == 0 else f'"{args.revision}"')
+ connection = http.client.HTTPConnection(url.hostname, port, timeout=12)
+ try:
+ connection.request('PUT', '/objects/' + args.key, payload, headers)
+ response = connection.getresponse()
+ body = response.read(LIMIT + 1)
+ if response.status != 200:
+ parser.error(f'storage response {response.status}: {response.getheader("X-Pure-Error")}')
+ if body != selected:
+ parser.error('response differs from the selection; check the installed program (write may have occurred)')
+ revision = response.getheader('ETag', '')
+ if not re.fullmatch(r'"[1-9][0-9]*"', revision) or int(revision[1:-1]) > 2**63 - 1:
+ parser.error('response has no valid stored revision (write may have occurred)')
+ except (OSError, http.client.HTTPException) as error:
+ parser.error(f'{error}; storage outcome is unknown if the request was sent')
+ finally:
+ connection.close()
+ print(json.dumps({'revision': revision[1:-1], 'selected': selected.decode('utf-8'),
+ 'stored_bytes': len(selected)}, ensure_ascii=False))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/selection.pure b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/selection.pure
new file mode 100644
index 0000000..7d9d4ec
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/selection.pure
@@ -0,0 +1,19 @@
+// This is an input boundary layout, not a required storage or RAM model.
+// The client sends two little-endian u32 values followed by document bytes.
+layout Selection {
+ start: u32le;
+ count: u32le;
+ document: bytes;
+}
+
+on get {
+ let saved = store.read(request.key);
+ reply(saved, saved.body);
+}
+
+on put {
+ let input = view(Selection, request.body);
+ let selected = range(input.document, input.start, input.count);
+ let saved = store.write(request.key, request.revision, selected);
+ reply(saved, selected);
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/storage.pure b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/storage.pure
new file mode 100644
index 0000000..ff54ea3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/examples/storage.pure
@@ -0,0 +1,11 @@
+// The host supplies request bytes, an object name, and the expected revision.
+// Failed storage results propagate to the host's response without executing reply.
+on get {
+ let object = store.read(request.key);
+ reply(object, object.body);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/flow.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/flow.c
new file mode 100644
index 0000000..1070c70
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/flow.c
@@ -0,0 +1,41 @@
+#include "flow.h"
+#include <assert.h>
+
+void pure_transfer_abort(PureTransfer *t) {
+ if (!t->active) return;
+ PureRelease release = t->release;
+ void *owner = t->owner;
+ *t = (PureTransfer){0};
+ if (release) release(owner);
+}
+
+static void advance(PureTransfer *t) {
+ while (t->active && t->part < 2 && t->offset == t->spans[t->part].size) {
+ t->part++;
+ t->offset = 0;
+ }
+ if (t->active && t->part == 2) pure_transfer_abort(t);
+}
+
+void pure_transfer_init(PureTransfer *t, PureSpan header, PureSpan body,
+ void *owner, PureRelease release) {
+ assert(!t->active);
+ assert((!header.size || header.data) && (!body.size || body.data));
+ *t = (PureTransfer){.spans = {header, body}, .owner = owner,
+ .release = release, .active = true};
+ advance(t);
+}
+
+PureSpan pure_transfer_next(const PureTransfer *t, size_t limit) {
+ if (!t->active) return (PureSpan){0};
+ PureSpan span = t->spans[t->part];
+ size_t remaining = span.size - t->offset;
+ return (PureSpan){span.data + t->offset, remaining < limit ? remaining : limit};
+}
+
+bool pure_transfer_consume(PureTransfer *t, size_t bytes) {
+ if (!t->active || bytes > t->spans[t->part].size - t->offset) return false;
+ t->offset += bytes;
+ advance(t);
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/flow.h b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/flow.h
new file mode 100644
index 0000000..6e27c58
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/flow.h
@@ -0,0 +1,25 @@
+#ifndef PURE_FLOW_H
+#define PURE_FLOW_H
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef struct { const unsigned char *data; size_t size; } PureSpan;
+typedef void (*PureRelease)(void *owner);
+
+/* A borrowed body stays alive until every byte is consumed or the transfer is
+ * aborted. A successful send() consumes bytes; peer receipt is a separate fact.
+ * Single owner thread; callbacks must not reenter or reuse this transfer. */
+typedef struct {
+ PureSpan spans[2];
+ size_t part, offset;
+ void *owner;
+ PureRelease release;
+ bool active;
+} PureTransfer;
+
+void pure_transfer_init(PureTransfer *, PureSpan header, PureSpan body,
+ void *owner, PureRelease);
+PureSpan pure_transfer_next(const PureTransfer *, size_t limit);
+bool pure_transfer_consume(PureTransfer *, size_t bytes);
+void pure_transfer_abort(PureTransfer *);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/program.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/program.c
new file mode 100644
index 0000000..8680782
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/program.c
@@ -0,0 +1,366 @@
+#include "program.h"
+#include "store.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+enum { NAME = 256, NUMBER, SYMBOLS = 32, LAYOUTS = 4, FIELDS = 16 };
+typedef enum { BYTE_VALUE, RESULT_VALUE, LAYOUT_VALUE, INDEX_VALUE } ValueKind;
+typedef struct {
+ char name[32];
+ ValueKind kind;
+ PureRegion region;
+ size_t step, layout;
+ PureIndex index;
+} Symbol;
+typedef struct {
+ char name[32];
+ size_t offset, length;
+ bool number, tail;
+} Field;
+typedef struct {
+ char name[32];
+ Field fields[FIELDS];
+ size_t count, prefix;
+ bool tail;
+} Layout;
+typedef struct {
+ const char *source;
+ size_t length, at, line, token_line;
+ int token;
+ char name[32];
+ size_t number;
+ char *error;
+ size_t error_size;
+ bool failed, put, effect;
+ Symbol symbols[SYMBOLS];
+ size_t count, layout_count;
+ Layout layouts[LAYOUTS];
+ PureProgram program;
+} Parser;
+
+static bool reject(Parser *p, const char *message) {
+ if (!p->failed && p->error_size) snprintf(p->error, p->error_size, "line %zu: %s", p->token_line, message);
+ p->failed = true;
+ return false;
+}
+
+static bool letter(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
+}
+
+static bool next(Parser *p) {
+ while (p->at < p->length) {
+ char c = p->source[p->at];
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ if (c == '\n') ++p->line;
+ ++p->at;
+ } else if (c == '/' && p->at + 1 < p->length && p->source[p->at + 1] == '/') {
+ while (p->at < p->length && p->source[p->at] != '\n') ++p->at;
+ } else break;
+ }
+ p->token_line = p->line;
+ p->name[0] = 0;
+ p->token = 0;
+ if (p->at == p->length) return true;
+ char c = p->source[p->at++];
+ if (letter(c)) {
+ size_t start = p->at - 1;
+ while (p->at < p->length && (letter(p->source[p->at]) ||
+ (p->source[p->at] >= '0' && p->source[p->at] <= '9'))) ++p->at;
+ size_t size = p->at - start;
+ if (size >= sizeof(p->name)) return reject(p, "name exceeds 31 bytes");
+ memcpy(p->name, p->source + start, size);
+ p->name[size] = 0;
+ p->token = NAME;
+ } else if (c >= '0' && c <= '9') {
+ size_t value = (size_t)(c - '0');
+ while (p->at < p->length && p->source[p->at] >= '0' && p->source[p->at] <= '9') {
+ unsigned digit = (unsigned)(p->source[p->at++] - '0');
+ if (value > (SIZE_MAX - digit) / 10) return reject(p, "integer overflow");
+ value = value * 10 + digit;
+ }
+ p->number = value;
+ p->token = NUMBER;
+ } else if (c && strchr("{}().,=;:[]", c)) p->token = (unsigned char)c;
+ else return reject(p, "unexpected character");
+ return true;
+}
+
+static bool is_word(Parser *p, const char *word) {
+ return p->token == NAME && !strcmp(p->name, word);
+}
+
+static bool word(Parser *p, const char *expected) {
+ return is_word(p, expected) ? next(p) : reject(p, expected);
+}
+
+static bool token(Parser *p, int expected) {
+ return p->token == expected ? next(p) : reject(p, "unexpected token");
+}
+
+static Symbol *find(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->count; ++i)
+ if (!strcmp(name, p->symbols[i].name)) return &p->symbols[i];
+ return NULL;
+}
+
+static bool field(Parser *p, const char *object, const char *name) {
+ return word(p, object) && token(p, '.') && word(p, name);
+}
+
+static bool require_bytes(Parser *p, const Symbol *value) {
+ return value->kind == BYTE_VALUE || reject(p, "expected bytes; select a byte field");
+}
+
+static void require_length(Parser *p, size_t required) {
+ size_t *minimum = p->put ? &p->program.input_required : &p->program.read_required;
+ if (required > *minimum) *minimum = required;
+}
+
+static Layout *find_layout(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->layout_count; ++i)
+ if (!strcmp(name, p->layouts[i].name)) return &p->layouts[i];
+ return NULL;
+}
+
+static bool layout_definition(Parser *p) {
+ if (p->layout_count == LAYOUTS) return reject(p, "program exceeds 4 layouts");
+ if (!next(p)) return false;
+ if (p->token != NAME || find_layout(p, p->name)) return reject(p, "expected a unique layout name");
+ Layout *layout = &p->layouts[p->layout_count];
+ strcpy(layout->name, p->name);
+ if (!next(p) || !token(p, '{')) return false;
+ while (p->token != '}') {
+ if (layout->count == FIELDS) return reject(p, "layout exceeds 16 fields");
+ if (layout->tail) return reject(p, "variable bytes must be the last field");
+ if (p->token != NAME) return reject(p, "expected a field name");
+ for (size_t i = 0; i < layout->count; ++i)
+ if (!strcmp(layout->fields[i].name, p->name)) return reject(p, "duplicate field");
+ Field *f = &layout->fields[layout->count];
+ strcpy(f->name, p->name);
+ f->offset = layout->prefix;
+ if (!next(p) || !token(p, ':')) return false;
+ if (is_word(p, "u32le")) {
+ f->number = true;
+ f->length = 4;
+ if (!next(p)) return false;
+ } else if (is_word(p, "bytes")) {
+ if (!next(p)) return false;
+ if (p->token == '[') {
+ if (!next(p)) return false;
+ if (p->token != NUMBER) return reject(p, "fixed bytes requires a constant size");
+ f->length = p->number;
+ if (!next(p) || !token(p, ']')) return false;
+ } else { f->tail = true; layout->tail = true; }
+ } else return reject(p, "supported field types: u32le, bytes[N], bytes");
+ if (f->length > PURE_OBJECT_LIMIT - layout->prefix) return reject(p, "layout exceeds object bound");
+ layout->prefix += f->length;
+ ++layout->count;
+ if (!token(p, ';')) return false;
+ }
+ if (!layout->count) return reject(p, "empty layout");
+ ++p->layout_count;
+ return token(p, '}');
+}
+
+static bool reference(Parser *p, Symbol *out) {
+ if (is_word(p, "request")) {
+ if (!p->put) return reject(p, "request.body is only available in on put");
+ *out = (Symbol){.kind = BYTE_VALUE, .region = {.to_end = true}};
+ return field(p, "request", "body");
+ }
+ Symbol *symbol = p->token == NAME ? find(p, p->name) : NULL;
+ if (!symbol) return reject(p, "unknown value");
+ *out = *symbol;
+ if (!next(p)) return false;
+ if (p->token != '.') return true;
+ if (!next(p)) return false;
+ if (symbol->kind == RESULT_VALUE) {
+ if (p->put) return reject(p, "write result has no body; use the input value");
+ *out = (Symbol){.kind = BYTE_VALUE, .region = {.to_end = true}};
+ return word(p, "body");
+ }
+ if (symbol->kind != LAYOUT_VALUE || p->token != NAME) return reject(p, "expected a layout field");
+ Layout *layout = &p->layouts[symbol->layout];
+ Field *f = NULL;
+ for (size_t i = 0; i < layout->count; ++i)
+ if (!strcmp(p->name, layout->fields[i].name)) f = &layout->fields[i];
+ if (!f) return reject(p, "unknown layout field");
+ size_t offset = symbol->region.offset + f->offset;
+ *out = (Symbol){.kind = f->number ? INDEX_VALUE : BYTE_VALUE};
+ if (f->number) out->index = (PureIndex){.value = offset, .from_u32le = true};
+ else out->region = (PureRegion){.offset = offset,
+ .length = f->tail ? (symbol->region.to_end ? 0 : symbol->region.length - f->offset) : f->length,
+ .to_end = f->tail && symbol->region.to_end};
+ return next(p);
+}
+
+static bool byte_reference(Parser *p, Symbol *out) {
+ return reference(p, out) && require_bytes(p, out);
+}
+
+static bool index_value(Parser *p, PureIndex *out) {
+ if (p->token == NUMBER) {
+ *out = (PureIndex){.value = p->number};
+ return next(p);
+ }
+ Symbol value;
+ if (!reference(p, &value)) return false;
+ if (value.kind != INDEX_VALUE) return reject(p, "range requires an integer or u32le field");
+ *out = value.index;
+ return true;
+}
+
+static bool layout_view(Parser *p, Symbol *out) {
+ if (!next(p) || !token(p, '(')) return false;
+ Layout *layout = p->token == NAME ? find_layout(p, p->name) : NULL;
+ if (!layout) return reject(p, "unknown layout");
+ if (!next(p) || !token(p, ',')) return false;
+ Symbol source;
+ if (!byte_reference(p, &source) || !token(p, ')')) return false;
+ if (source.step) return reject(p, "layout view requires a statically located source");
+ size_t bound = source.region.to_end ? PURE_OBJECT_LIMIT - source.region.offset : source.region.length;
+ if (layout->prefix > bound) return reject(p, "layout exceeds source bound");
+ require_length(p, source.region.offset + layout->prefix);
+ *out = (Symbol){.kind = LAYOUT_VALUE, .region = source.region, .layout = (size_t)(layout - p->layouts)};
+ if (!layout->tail) { out->region.length = layout->prefix; out->region.to_end = false; }
+ return true;
+}
+
+static bool view(Parser *p, Symbol *out) {
+ if (is_word(p, "view")) return layout_view(p, out);
+ if (!is_word(p, "range")) return reference(p, out);
+ Symbol parent;
+ PureIndex offset, length;
+ if (!next(p) || !token(p, '(') || !byte_reference(p, &parent) || !token(p, ',') ||
+ !index_value(p, &offset) || !token(p, ',') || !index_value(p, &length) || !token(p, ')')) return false;
+ bool dynamic = parent.step || offset.from_u32le || length.from_u32le;
+ *out = (Symbol){.kind = BYTE_VALUE};
+ if (dynamic) {
+ if (!p->put) return reject(p, "data-dependent ranges currently require PUT input");
+ if (p->program.input_steps == PURE_DYNAMIC_LIMIT) return reject(p, "input exceeds 8 dynamic ranges");
+ if ((!offset.from_u32le && offset.value > PURE_OBJECT_LIMIT) ||
+ (!length.from_u32le && length.value > PURE_OBJECT_LIMIT)) return reject(p, "range exceeds object bound");
+ PureRangeStep *step = &p->program.steps[p->program.input_steps++];
+ *step = (PureRangeStep){.source = parent.region, .source_step = parent.step,
+ .offset = offset, .length = length};
+ out->step = p->program.input_steps;
+ } else {
+ size_t bound = parent.region.to_end ? PURE_OBJECT_LIMIT - parent.region.offset : parent.region.length;
+ if (offset.value > bound || length.value > bound - offset.value) return reject(p, "range exceeds its source bound");
+ out->region = (PureRegion){.offset = parent.region.offset + offset.value, .length = length.value};
+ require_length(p, out->region.offset + out->region.length);
+ }
+ ++p->program.range_definitions;
+ return true;
+}
+
+static bool effect(Parser *p, Symbol *out) {
+ if (p->effect) return reject(p, "only one storage effect is supported per handler");
+ if (!word(p, "store") || !token(p, '.')) return false;
+ bool splice = p->put && is_word(p, "splice");
+ if (!word(p, p->put ? (splice ? "splice" : "write") : "read") ||
+ !token(p, '(') || !field(p, "request", "key")) return false;
+ if (p->put) {
+ Symbol value;
+ if (!token(p, ',') || !field(p, "request", "revision") || !token(p, ',')) return false;
+ if (splice) {
+ if (!index_value(p, &p->program.splice_offset) || !token(p, ',') ||
+ !index_value(p, &p->program.splice_remove) || !token(p, ',')) return false;
+ if ((!p->program.splice_offset.from_u32le && p->program.splice_offset.value > PURE_OBJECT_LIMIT) ||
+ (!p->program.splice_remove.from_u32le && p->program.splice_remove.value > PURE_OBJECT_LIMIT))
+ return reject(p, "splice exceeds object bound");
+ p->program.splice = true;
+ }
+ if (!byte_reference(p, &value)) return false;
+ p->program.write = value.region;
+ p->program.write_step = value.step;
+ }
+ if (!token(p, ')')) return false;
+ out->kind = RESULT_VALUE;
+ p->effect = true;
+ return true;
+}
+
+static bool handler(Parser *p) {
+ p->count = 0;
+ p->effect = false;
+ if (!token(p, '{')) return false;
+ while (is_word(p, "let")) {
+ if (p->put && p->effect) return reject(p, "all views must precede the storage effect; reply must follow it");
+ if (p->count == SYMBOLS) return reject(p, "handler exceeds 32 definitions");
+ if (!next(p)) return false;
+ if (p->token != NAME || is_word(p, "request") || is_word(p, "store") ||
+ is_word(p, "range") || is_word(p, "view")) return reject(p, "expected a non-reserved definition name");
+ if (find(p, p->name)) return reject(p, "duplicate definition");
+ char name[32];
+ strcpy(name, p->name);
+ Symbol symbol = {0};
+ if (!next(p) || !token(p, '=')) return false;
+ if (is_word(p, "store")) {
+ if (!effect(p, &symbol)) return false;
+ } else {
+ if (!view(p, &symbol)) return false;
+ ++p->program.view_definitions;
+ }
+ if (!token(p, ';')) return false;
+ strcpy(symbol.name, name);
+ p->symbols[p->count++] = symbol;
+ }
+ if (!p->effect) return reject(p, "handler requires its storage effect");
+ if (!word(p, "reply") || !token(p, '(')) return false;
+ Symbol *result = p->token == NAME ? find(p, p->name) : NULL;
+ if (!result || result->kind != RESULT_VALUE) return reject(p, "reply requires this handler's storage result");
+ if (!next(p)) return false;
+ Symbol body = {0};
+ bool has_body = p->token == ',';
+ if (has_body && (!next(p) || !byte_reference(p, &body))) return false;
+ if (!token(p, ')') || !token(p, ';') || !token(p, '}')) return false;
+ if (p->put) {
+ p->program.reply = body.region;
+ p->program.reply_step = body.step;
+ p->program.reply_input = has_body;
+ } else p->program.read = body.region;
+ return true;
+}
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size) {
+ Parser p = {.source = source, .length = length, .line = 1, .token_line = 1,
+ .error = error, .error_size = error_size};
+ if (error_size) error[0] = 0;
+ if (length > PURE_PROGRAM_LIMIT) return reject(&p, "program exceeds 16 KiB");
+ if (!next(&p)) return false;
+ while (is_word(&p, "layout")) if (!layout_definition(&p)) return false;
+ unsigned handlers = 0;
+ while (p.token) {
+ if (!word(&p, "on")) return false;
+ if (!is_word(&p, "get") && !is_word(&p, "put")) return reject(&p, "expected get or put handler");
+ p.put = is_word(&p, "put");
+ unsigned bit = p.put ? 2 : 1;
+ if (handlers & bit) return reject(&p, "duplicate handler");
+ handlers |= bit;
+ if (!next(&p) || !handler(&p)) return false;
+ }
+ if (handlers != 3) return reject(&p, "both get and put handlers are required");
+ *out = p.program; /* Invalid preparation never changes the installed plan. */
+ return true;
+}
+
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size) {
+ FILE *file = fopen(path, "rb");
+ if (!file) {
+ if (error_size) snprintf(error, error_size, "cannot open program");
+ return false;
+ }
+ char source[PURE_PROGRAM_LIMIT + 1];
+ size_t length = fread(source, 1, sizeof(source), file);
+ bool bad = ferror(file) != 0;
+ if (fclose(file)) bad = true;
+ if (bad) {
+ if (error_size) snprintf(error, error_size, "cannot read program");
+ return false;
+ }
+ return pure_program_parse(source, length, out, error, error_size);
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/program.h b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/program.h
new file mode 100644
index 0000000..c102eb1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/program.h
@@ -0,0 +1,44 @@
+#ifndef PURE_PROGRAM_H
+#define PURE_PROGRAM_H
+#include "flow.h"
+
+#define PURE_PROGRAM_LIMIT 16384u
+#define PURE_DYNAMIC_LIMIT 8u
+typedef struct {
+ size_t offset, length;
+ bool to_end;
+} PureRegion;
+
+typedef struct { size_t value; bool from_u32le; } PureIndex;
+typedef struct {
+ PureRegion source;
+ size_t source_step; /* 0: source region; otherwise a preceding step + 1. */
+ PureIndex offset, length;
+} PureRangeStep;
+
+/* Prepared connections, not an instruction stream. All view definitions are
+ * checked at preparation; their root-length requirements survive elimination.
+ * Input views are evaluated before the write effect. A read still opens and
+ * validates the object even if its response has no body. */
+typedef struct {
+ PureRegion read, write, reply;
+ size_t read_required, input_required;
+ size_t view_definitions, range_definitions;
+ size_t write_step, reply_step, input_steps;
+ PureRangeStep steps[PURE_DYNAMIC_LIMIT];
+ bool reply_input;
+ bool splice;
+ PureIndex splice_offset, splice_remove;
+} PureProgram;
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size);
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size);
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out);
+/* Validates all input views, including unused dynamic views, before any effect.
+ * Returns borrowed selections; their lifetime remains that of source. */
+bool pure_program_input(const PureProgram *, PureSpan source, PureSpan *write, PureSpan *reply);
+/* Byte positions in the stored value. Bounds against the current version are
+ * checked by the conditional storage effect under the writer lock. */
+bool pure_program_splice(const PureProgram *, PureSpan source, size_t *offset, size_t *remove);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/result.h b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/result.h
new file mode 100644
index 0000000..8abb0f2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/result.h
@@ -0,0 +1,8 @@
+#ifndef PURE_RESULT_H
+#define PURE_RESULT_H
+typedef enum {
+ PURE_OK, PURE_NOT_FOUND, PURE_CONFLICT, PURE_BUSY, PURE_BUDGET,
+ PURE_LIMIT, PURE_STORE_ERROR, PURE_UNCERTAIN,
+ PURE_INVALID, PURE_DENIED, PURE_CLOSED, PURE_CANCELLED, PURE_ALLOCATION
+} PureResult;
+#endif
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/runtime.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/runtime.c
new file mode 100644
index 0000000..aa4ed05
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/runtime.c
@@ -0,0 +1,273 @@
+#include "runtime.h"
+#include <string.h>
+
+#define NONE SIZE_MAX
+enum { FREE, RECEIVING, READY, RUNNING, DONE };
+
+static PureWork *lookup(PureTicket ticket, bool require_held) {
+ PureRuntime *r = ticket.runtime;
+ if (!r || ticket.slot >= r->capacity || !ticket.generation) return NULL;
+ PureWork *w = &r->work[ticket.slot];
+ if (w->state == FREE || w->generation != ticket.generation ||
+ (require_held && !w->held)) return NULL;
+ return w;
+}
+
+static bool valid_key(const char *key) {
+ if (!key || !*key) return false;
+ size_t n = 0;
+ for (; n <= 64 && key[n]; ++n) {
+ unsigned char c = (unsigned char)key[n];
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || c == '-' || c == '_')) return false;
+ }
+ return n <= 64;
+}
+
+static void dispose(PureResource *resource) {
+ PureResource old = *resource;
+ *resource = (PureResource){0};
+ if (old.release) old.release(old.allocation, old.allocation_size);
+}
+
+static void payload_release(PureRuntime *r, PureWork *w);
+
+/* Iteratively retire a chain of forwarded values. An arbitrarily long chain
+ * must not turn completion into recursive stack growth. */
+static void retire(PureRuntime *r, PureWork *w) {
+ while (w && !w->held && !w->pins) {
+ PureTicket parent = w->parent;
+ bool owned = w->charged || w->resource.release || parent.runtime;
+ dispose(&w->resource);
+ r->retained -= w->charged;
+ if (owned) ++r->releases;
+ size_t slot = (size_t)(w - r->work);
+ *w = (PureWork){.next = r->free_head};
+ r->free_head = slot;
+ --r->active;
+ if (!parent.runtime) break;
+ r = parent.runtime;
+ w = lookup(parent, false);
+ /* Pins can only be created and removed by the owner-thread core. */
+ if (!w || !w->pins) break;
+ --w->pins;
+ }
+}
+
+static void payload_release(PureRuntime *r, PureWork *w) {
+ PureTicket parent = w->parent;
+ bool owned = w->charged || w->resource.release || parent.runtime;
+ dispose(&w->resource);
+ r->retained -= w->charged;
+ w->charged = 0;
+ w->parent = (PureTicket){0};
+ if (owned) ++r->releases;
+ if (parent.runtime) {
+ PureWork *source = lookup(parent, false);
+ if (source && source->pins) { --source->pins; retire(parent.runtime, source); }
+ }
+}
+
+bool pure_runtime_init(PureRuntime *r, PureWork *work, size_t capacity,
+ const PureProgram *program, PureHost host, size_t budget) {
+ if (!r || !work || !capacity || !program) return false;
+ *r = (PureRuntime){.program = program, .host = host, .work = work,
+ .capacity = capacity, .free_head = 0, .ready_head = NONE, .ready_tail = NONE,
+ .budget = budget, .accepting = true};
+ for (size_t i = 0; i < capacity; ++i)
+ work[i] = (PureWork){.next = i + 1 < capacity ? i + 1 : NONE};
+ return true;
+}
+
+bool pure_runtime_restart(PureRuntime *r, const PureProgram *p, PureHost host, size_t budget) {
+ if (!r || !p || r->running || r->active) return false;
+ r->program = p;
+ r->host = host;
+ r->budget = budget;
+ r->accepting = true;
+ return true;
+}
+
+void pure_runtime_stop(PureRuntime *r) { if (r && !r->running) r->accepting = false; }
+
+static PureResult admission(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t bytes) {
+ if (!r || r->running || !valid_key(key) ||
+ (input != PURE_INPUT_READ && input != PURE_INPUT_WRITE) ||
+ (input == PURE_INPUT_READ ? bytes != 0 : expected < 0)) return PURE_INVALID;
+ if (!r->accepting) return PURE_CLOSED;
+ if (input == PURE_INPUT_READ ? !r->host.read :
+ (r->program->splice ? !r->host.splice : !r->host.write)) return PURE_DENIED;
+ if (r->free_head == NONE) return PURE_BUSY;
+ if (r->serial == UINT64_MAX) return PURE_LIMIT;
+ if (bytes > r->budget - r->retained) { ++r->budget_rejections; return PURE_BUDGET; }
+ return PURE_OK;
+}
+
+static PureTicket occupy(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t bytes, PureResource resource) {
+ size_t slot = r->free_head;
+ PureWork *w = &r->work[slot];
+ r->free_head = w->next;
+ *w = (PureWork){.generation = ++r->serial, .next = NONE, .charged = bytes,
+ .state = RECEIVING, .held = true, .input = input, .expected = expected,
+ .resource = resource};
+ memcpy(w->key, key, strlen(key) + 1);
+ ++r->active;
+ ++r->accepted;
+ r->retained += bytes;
+ if (r->active > r->peak_active) r->peak_active = r->active;
+ if (r->retained > r->peak_retained) r->peak_retained = r->retained;
+ return (PureTicket){r, slot, w->generation};
+}
+
+bool pure_runtime_ready(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running || w->state != RECEIVING) return false;
+ PureRuntime *r = ticket.runtime;
+ w->state = READY;
+ if (r->ready_tail == NONE) r->ready_head = ticket.slot;
+ else r->work[r->ready_tail].next = ticket.slot;
+ r->ready_tail = ticket.slot;
+ return true;
+}
+
+PureResult pure_runtime_accept(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t size, PureTicket *out) {
+ if (!out) return PURE_INVALID;
+ PureResult status = admission(r, input, key, expected, size);
+ if (status != PURE_OK) return status;
+ PureResource resource = {0};
+ if (size) {
+ if (!r->host.allocate) return PURE_ALLOCATION;
+ r->running = true;
+ bool ok = r->host.allocate(r->host.context, size, &resource);
+ r->running = false;
+ if (!ok || !resource.body.data || resource.body.size != size || !resource.release) {
+ dispose(&resource);
+ return PURE_ALLOCATION;
+ }
+ }
+ *out = occupy(r, input, key, expected, size, resource);
+ if (input == PURE_INPUT_READ) pure_runtime_ready(*out);
+ return PURE_OK;
+}
+
+unsigned char *pure_runtime_ingress(PureTicket ticket, size_t *size) {
+ PureWork *w = lookup(ticket, true);
+ if (size) *size = 0;
+ if (!w || ticket.runtime->running || w->state != RECEIVING ||
+ w->input != PURE_INPUT_WRITE || w->parent.runtime) return NULL;
+ if (size) *size = w->resource.body.size;
+ return (unsigned char *)w->resource.body.data;
+}
+
+bool pure_runtime_step(PureRuntime *r) {
+ if (!r || r->running || r->ready_head == NONE) return false;
+ size_t slot = r->ready_head;
+ PureWork *w = &r->work[slot];
+ r->ready_head = w->next;
+ if (r->ready_head == NONE) r->ready_tail = NONE;
+ w->next = NONE;
+ w->state = RUNNING;
+ r->running = true;
+ PureOutcome outcome = {0};
+ if (w->input == PURE_INPUT_WRITE) {
+ PureSpan value;
+ size_t offset = 0, remove = 0;
+ if (!pure_program_input(r->program, w->resource.body, &value, &outcome.body))
+ outcome.status = PURE_LIMIT;
+ else if (r->program->splice) {
+ if (!pure_program_splice(r->program, w->resource.body, &offset, &remove))
+ outcome.status = PURE_LIMIT;
+ else outcome.status = r->host.splice(r->host.context, w->key, w->expected,
+ offset, remove, value, &outcome.revision);
+ }
+ else outcome.status = r->host.write(r->host.context, w->key, w->expected,
+ value, &outcome.revision);
+ if (outcome.status == PURE_OK) ++r->commits;
+ else if (outcome.status == PURE_CONFLICT) ++r->conflicts;
+ } else {
+ outcome.status = r->host.read(r->host.context, w->key, r->program->read,
+ r->program->read_required, r->budget - r->retained, &w->resource, &outcome.revision);
+ if (outcome.status == PURE_OK) {
+ if (w->resource.body.size > r->budget - r->retained) outcome.status = PURE_BUDGET;
+ else if (w->resource.body.size && (!w->resource.body.data || !w->resource.release))
+ outcome.status = PURE_STORE_ERROR;
+ else {
+ w->charged = w->resource.body.size;
+ r->retained += w->charged;
+ if (r->retained > r->peak_retained) r->peak_retained = r->retained;
+ outcome.body = w->resource.body;
+ ++r->gets;
+ }
+ }
+ if (outcome.status == PURE_BUDGET) ++r->budget_rejections;
+ }
+ if (outcome.status != PURE_OK || !outcome.body.size) {
+ outcome.body = (PureSpan){0};
+ payload_release(r, w);
+ }
+ r->borrowed_output_bytes += outcome.body.size;
+ w->outcome = outcome;
+ w->state = DONE;
+ r->running = false;
+ return true;
+}
+
+bool pure_runtime_result(PureTicket ticket, PureOutcome *out) {
+ PureWork *w = lookup(ticket, true);
+ if (!out || !w || ticket.runtime->running || w->state != DONE) return false;
+ *out = w->outcome;
+ return true;
+}
+
+PureResult pure_runtime_forward(PureTicket source, PureRuntime *r,
+ const char *key, int64_t expected, PureTicket *out) {
+ PureWork *parent = lookup(source, true);
+ if (!out || !parent || source.runtime->running || parent->state != DONE ||
+ parent->outcome.status != PURE_OK) return PURE_INVALID;
+ PureResult status = admission(r, PURE_INPUT_WRITE, key, expected, parent->outcome.body.size);
+ if (status != PURE_OK) return status;
+ if (parent->pins == SIZE_MAX) return PURE_LIMIT;
+ PureTicket ticket = occupy(r, PURE_INPUT_WRITE, key, expected, parent->outcome.body.size,
+ (PureResource){.body = parent->outcome.body});
+ ++parent->pins;
+ r->work[ticket.slot].parent = source;
+ pure_runtime_ready(ticket);
+ *out = ticket;
+ return PURE_OK;
+}
+
+static void unlink_ready(PureRuntime *r, size_t slot) {
+ size_t previous = NONE;
+ for (size_t at = r->ready_head; at != NONE; at = r->work[at].next) {
+ if (at == slot) {
+ if (previous == NONE) r->ready_head = r->work[at].next;
+ else r->work[previous].next = r->work[at].next;
+ if (r->ready_tail == at) r->ready_tail = previous;
+ r->work[at].next = NONE;
+ return;
+ }
+ previous = at;
+ }
+}
+
+bool pure_runtime_cancel(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running || (w->state != RECEIVING && w->state != READY)) return false;
+ if (w->state == READY) unlink_ready(ticket.runtime, ticket.slot);
+ payload_release(ticket.runtime, w);
+ w->outcome = (PureOutcome){.status = PURE_CANCELLED};
+ w->state = DONE;
+ return true;
+}
+
+bool pure_runtime_release(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running) return false;
+ if (w->state == READY) unlink_ready(ticket.runtime, ticket.slot);
+ w->held = false;
+ retire(ticket.runtime, w);
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/runtime.h b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/runtime.h
new file mode 100644
index 0000000..1bff082
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/runtime.h
@@ -0,0 +1,88 @@
+#ifndef PURE_RUNTIME_H
+#define PURE_RUNTIME_H
+#include "program.h"
+#include "result.h"
+#include <stdint.h>
+
+/* First execution profile: authored selection -> read/conditional write ->
+ * reply. No socket, file descriptor, allocator, parser or OS type in the core.
+ * All control calls and connected domains share one owner thread. Host effects
+ * are synchronous in this profile and must not reenter the runtime. */
+typedef struct PureRuntime PureRuntime;
+typedef struct PureWork PureWork;
+typedef struct { PureRuntime *runtime; size_t slot; uint64_t generation; } PureTicket;
+typedef enum { PURE_INPUT_READ, PURE_INPUT_WRITE } PureInput;
+
+/* The host owns this resource until it successfully returns it to the core.
+ * release must end all access and free/unmap allocation exactly once. */
+typedef struct {
+ PureSpan body;
+ void *allocation;
+ size_t allocation_size;
+ void (*release)(void *allocation, size_t size);
+} PureResource;
+typedef struct {
+ void *context;
+ bool (*allocate)(void *, size_t, PureResource *);
+ PureResult (*read)(void *, const char *, PureRegion, size_t minimum,
+ size_t available, PureResource *, int64_t *revision);
+ PureResult (*write)(void *, const char *, int64_t expected,
+ PureSpan, int64_t *revision);
+ PureResult (*splice)(void *, const char *, int64_t expected, size_t offset,
+ size_t remove, PureSpan insert, int64_t *revision);
+} PureHost;
+typedef struct { PureResult status; int64_t revision; PureSpan body; } PureOutcome;
+
+/* Caller-provided work slots: no background thread or per-domain heap. These
+ * records are implementation storage, not an ABI or a wire representation. */
+struct PureWork {
+ uint64_t generation;
+ size_t next, charged, pins;
+ unsigned state;
+ bool held;
+ PureInput input;
+ int64_t expected;
+ char key[65];
+ PureResource resource;
+ PureTicket parent;
+ PureOutcome outcome;
+};
+struct PureRuntime {
+ const PureProgram *program;
+ PureHost host;
+ PureWork *work;
+ size_t capacity, free_head, ready_head, ready_tail;
+ size_t budget, retained, peak_retained, active, peak_active;
+ uint64_t serial, accepted, commits, gets, conflicts, budget_rejections;
+ uint64_t releases, borrowed_output_bytes;
+ bool accepting, running;
+};
+
+/* Initialize fresh storage once. Use restart, not init, to reuse a domain;
+ * the monotonic ticket sequence then survives restart. program is immutable
+ * and remains alive until all work has drained. */
+bool pure_runtime_init(PureRuntime *, PureWork *, size_t capacity,
+ const PureProgram *, PureHost, size_t budget);
+bool pure_runtime_restart(PureRuntime *, const PureProgram *, PureHost, size_t budget);
+void pure_runtime_stop(PureRuntime *); /* stop admission, allow queued work to drain */
+
+/* READ queues immediately. WRITE reserves its slot, budget and host allocation
+ * before returning. Fill ingress then publish once with ready. A partial input
+ * released without ready never executes. On error, out is unchanged. */
+PureResult pure_runtime_accept(PureRuntime *, PureInput, const char *key,
+ int64_t expected, size_t input_size, PureTicket *out);
+unsigned char *pure_runtime_ingress(PureTicket, size_t *size);
+bool pure_runtime_ready(PureTicket);
+bool pure_runtime_step(PureRuntime *); /* execute at most one ready job */
+bool pure_runtime_result(PureTicket, PureOutcome *out);
+
+/* Pin a completed reply and queue it as another domain's WRITE input, with no
+ * allocation, serialization or payload copy. Source may be released as soon
+ * as this succeeds; the core retains its backing until the consumer ends.
+ * Each domain charges its own retained input bytes as admission credits.
+ * Credits across domains are NOT distinct physical memory and must not be summed. */
+PureResult pure_runtime_forward(PureTicket source, PureRuntime *destination,
+ const char *key, int64_t expected, PureTicket *out);
+bool pure_runtime_cancel(PureTicket); /* only before execution; keeps a completion */
+bool pure_runtime_release(PureTicket); /* invalidates caller's ticket, preserves pins */
+#endif
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/server.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/server.c
new file mode 100644
index 0000000..50480c0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/server.c
@@ -0,0 +1,372 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include "program.h"
+#include "store-port.h"
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+enum { SLOTS = 8, HEADER_LIMIT = 4096, CHUNK = 65536 };
+typedef enum { READING_HEADER, READING_BODY, WRITING } Phase;
+typedef struct Server Server;
+typedef struct {
+ int fd;
+ Phase phase;
+ uint64_t deadline;
+ char request[HEADER_LIMIT + 1], response[512], key[65];
+ size_t header_size, body_size, received;
+ unsigned char *body;
+ bool put;
+ int64_t expected;
+ PureTicket ticket;
+ PureTransfer transfer;
+ Server *server;
+} Connection;
+struct Server {
+ const char *path;
+ PureProgram program;
+ PureRuntime runtime;
+ PureWork work[SLOTS];
+ size_t budget, active, peak_active;
+ uint64_t accepted, expired, prefix_copy_bytes;
+ uint64_t timeout_ms;
+ int send_buffer;
+ Connection connections[SLOTS];
+};
+static volatile sig_atomic_t stopping;
+static void stop_server(int sig) { (void)sig; stopping = 1; }
+
+static uint64_t now_ms(void) {
+ struct timespec t;
+ if (clock_gettime(CLOCK_MONOTONIC, &t)) abort();
+ return (uint64_t)t.tv_sec * 1000 + (uint64_t)t.tv_nsec / 1000000;
+}
+
+static bool number(const char *text, uint64_t maximum, uint64_t *value) {
+ if (!*text) return false;
+ uint64_t n = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > maximum || n > (maximum - digit) / 10) return false;
+ n = n * 10 + digit;
+ }
+ *value = n;
+ return true;
+}
+
+static void release_payload(void *owner) {
+ Connection *c = owner;
+ if (c->ticket.runtime) {
+ bool released = pure_runtime_release(c->ticket);
+ assert(released);
+ (void)released;
+ }
+ c->ticket = (PureTicket){0};
+ c->body = NULL;
+}
+
+static void close_connection(Connection *c) {
+ if (c->fd < 0) return;
+ if (c->transfer.active) pure_transfer_abort(&c->transfer);
+ else release_payload(c);
+ close(c->fd);
+ --c->server->active;
+ *c = (Connection){.fd = -1};
+}
+
+static void respond(Connection *c, int status, const char *reason, const char *error,
+ int64_t revision, PureSpan body) {
+ char tag[80] = "";
+ if (revision > 0) snprintf(tag, sizeof(tag), "ETag: \"%" PRId64 "\"\r\n", revision);
+ int length = snprintf(c->response, sizeof(c->response),
+ "HTTP/1.1 %d %s\r\nContent-Length: %zu\r\nConnection: close\r\n"
+ "Content-Type: application/octet-stream\r\nCache-Control: no-store\r\n"
+ "X-Pure-Error: %s\r\n%s\r\n", status, reason, body.size, error, tag);
+ assert(length > 0 && (size_t)length < sizeof(c->response));
+ c->phase = WRITING;
+ pure_transfer_init(&c->transfer,
+ (PureSpan){(const unsigned char *)c->response, (size_t)length}, body, c, release_payload);
+}
+
+static void fail(Connection *c, int status, const char *reason, const char *error) {
+ /* No outstanding backend access on the owner thread at this point. */
+ release_payload(c);
+ respond(c, status, reason, error, 0, (PureSpan){0});
+}
+
+static void answer(Connection *c, PureOutcome result) {
+ switch (result.status) {
+ case PURE_OK: respond(c, 200, "OK", "none", result.revision, result.body); break;
+ case PURE_NOT_FOUND: fail(c, 404, "Not Found", "not_found"); break;
+ case PURE_CONFLICT:
+ respond(c, 412, "Precondition Failed", "conflict", result.revision, (PureSpan){0}); break;
+ case PURE_BUSY: fail(c, 503, "Service Unavailable", "store_busy"); break;
+ case PURE_BUDGET: fail(c, 503, "Service Unavailable", "payload_budget"); break;
+ case PURE_ALLOCATION: fail(c, 503, "Service Unavailable", "allocation"); break;
+ case PURE_CLOSED: fail(c, 503, "Service Unavailable", "stopped"); break;
+ case PURE_DENIED: fail(c, 403, "Forbidden", "denied"); break;
+ case PURE_LIMIT: fail(c, 413, "Content Too Large", "limit"); break;
+ case PURE_UNCERTAIN: fail(c, 500, "Internal Server Error", "durability_unknown"); break;
+ default: fail(c, 500, "Internal Server Error", "storage"); break;
+ }
+}
+
+static void run_request(Connection *c) {
+ if (c->put && !pure_runtime_ready(c->ticket)) abort();
+ PureOutcome result;
+ while (!pure_runtime_result(c->ticket, &result))
+ if (!pure_runtime_step(&c->server->runtime)) abort();
+ c->body = NULL; /* Core now owns input until all consumers release it. */
+ answer(c, result);
+}
+
+/* Deliberately bounded HTTP/1.1 subset: one GET/PUT, Content-Length, close.
+ * No transfer coding, pipelining, trailers, Expect, URL decoding, or proxying. */
+static bool parse_header(Connection *c, size_t end) {
+ for (size_t i = 0; i < end; ++i) {
+ unsigned char b = (unsigned char)c->request[i];
+ if ((b < 32 && b != '\r' && b != '\n' && b != '\t') || b == 127) return false;
+ }
+ char *line = c->request, *next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *path = strchr(line, ' ');
+ if (!path) return false;
+ *path++ = 0;
+ if (strcmp(line, "PUT") == 0) c->put = true;
+ else if (strcmp(line, "GET") != 0) return false;
+ char *version = strchr(path, ' ');
+ if (!version) return false;
+ *version++ = 0;
+ if (strcmp(version, "HTTP/1.1") || strncmp(path, "/objects/", 9)) return false;
+ const char *key = path + 9;
+ size_t key_size = strlen(key);
+ if (!key_size || key_size > 64) return false;
+ for (size_t i = 0; i < key_size; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ memcpy(c->key, key, key_size + 1);
+ bool length_seen = false, condition_seen = false, host_seen = false;
+ line = next + 2;
+ while (*line != '\r') {
+ next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *value = strchr(line, ':');
+ if (!value || value == line) return false;
+ *value++ = 0;
+ for (char *p = line; *p; ++p)
+ if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') || *p == '-')) return false;
+ while (*value == ' ' || *value == '\t') ++value;
+ char *tail = value + strlen(value);
+ while (tail > value && (tail[-1] == ' ' || tail[-1] == '\t')) *--tail = 0;
+ if (strchr(value, '\r') || strchr(value, '\n')) return false;
+ uint64_t n;
+ if (!strcasecmp(line, "Content-Length")) {
+ if (length_seen || !number(value, SIZE_MAX, &n)) return false;
+ length_seen = true;
+ c->body_size = (size_t)n;
+ } else if (!strcasecmp(line, "Host")) {
+ if (host_seen || !*value) return false;
+ host_seen = true;
+ } else if (!strcasecmp(line, "If-Match")) {
+ if (condition_seen || tail - value < 3 || *value != '"' || tail[-1] != '"') return false;
+ tail[-1] = 0;
+ if (!number(value + 1, INT64_MAX, &n) || !n) return false;
+ c->expected = (int64_t)n;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "If-None-Match")) {
+ if (condition_seen || strcmp(value, "*")) return false;
+ c->expected = 0;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "Transfer-Encoding") || !strcasecmp(line, "Expect")) return false;
+ line = next + 2;
+ }
+ return host_seen && (c->put ? length_seen && condition_seen : !condition_seen && c->body_size == 0);
+}
+
+static void read_connection(Connection *c) {
+ if (c->phase == READING_HEADER) {
+ ssize_t n = recv(c->fd, c->request + c->header_size, HEADER_LIMIT - c->header_size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->header_size += (size_t)n;
+ c->request[c->header_size] = 0;
+ /* Scan by byte count, so embedded NUL cannot hide a terminator. */
+ size_t end = 0;
+ for (size_t i = 3; i < c->header_size; ++i)
+ if (!memcmp(c->request + i - 3, "\r\n\r\n", 4)) { end = i + 1; break; }
+ if (!end) {
+ if (c->header_size == HEADER_LIMIT) fail(c, 431, "Request Header Fields Too Large", "headers");
+ return;
+ }
+ size_t prefix = c->header_size - end;
+ if (!parse_header(c, end)) { fail(c, 400, "Bad Request", "request"); return; }
+ if (c->body_size > PURE_OBJECT_LIMIT) { fail(c, 413, "Content Too Large", "limit"); return; }
+ if (prefix > c->body_size) { fail(c, 400, "Bad Request", "extra_body"); return; }
+ PureResult admitted = pure_runtime_accept(&c->server->runtime,
+ c->put ? PURE_INPUT_WRITE : PURE_INPUT_READ, c->key, c->expected, c->body_size, &c->ticket);
+ if (admitted != PURE_OK) { answer(c, (PureOutcome){.status = admitted}); return; }
+ if (!c->put) { run_request(c); return; }
+ c->body = pure_runtime_ingress(c->ticket, NULL);
+ if (prefix) memcpy(c->body, c->request + end, prefix);
+ c->server->prefix_copy_bytes += prefix;
+ c->received = prefix;
+ c->phase = READING_BODY;
+ if (c->received == c->body_size) run_request(c);
+ } else {
+ size_t remaining = c->body_size - c->received;
+ ssize_t n = recv(c->fd, c->body + c->received, remaining < CHUNK ? remaining : CHUNK, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->received += (size_t)n;
+ if (c->received == c->body_size) run_request(c);
+ }
+}
+
+static void write_connection(Connection *c) {
+ PureSpan span = pure_transfer_next(&c->transfer, CHUNK);
+ ssize_t n = send(c->fd, span.data, span.size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ if (!pure_transfer_consume(&c->transfer, (size_t)n)) abort();
+ if (!c->transfer.active) close_connection(c);
+}
+
+static bool nonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
+}
+
+int main(int argc, char **argv) {
+ Server server = {.budget = 4u * 1024u * 1024u, .timeout_ms = 10000};
+ unsigned port = 8767;
+ const char *program_path = NULL;
+ bool explain = argc == 3 && !strcmp(argv[1], "--check-program");
+ char program_error[160];
+ if (explain) program_path = argv[2];
+ for (int i = 1; !explain && i < argc; i += 2) {
+ if (i + 1 == argc) goto usage;
+ uint64_t value;
+ if (!strcmp(argv[i], "--store")) server.path = argv[i + 1];
+ else if (!strcmp(argv[i], "--program")) program_path = argv[i + 1];
+ else if (!strcmp(argv[i], "--port") && number(argv[i + 1], 65535, &value)) port = (unsigned)value;
+ else if (!strcmp(argv[i], "--budget") && number(argv[i + 1], SIZE_MAX, &value) && value) server.budget = (size_t)value;
+ else if (!strcmp(argv[i], "--timeout-ms") && number(argv[i + 1], 3600000, &value) && value) server.timeout_ms = value;
+ else if (!strcmp(argv[i], "--send-buffer") && number(argv[i + 1], INT32_MAX, &value)) server.send_buffer = (int)value;
+ else goto usage;
+ }
+ if (!program_path || (!explain && !server.path)) goto usage;
+ if (!pure_program_load(program_path, &server.program, program_error, sizeof(program_error))) {
+ fprintf(stderr, "Program: %s\n", program_error); return 2;
+ }
+ if (explain) {
+ PureProgram *p = &server.program;
+ printf("{\"read\":{\"to_end\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"write\":{\"to_end\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"reply_input\":%s,\"view_definitions\":%zu,\"range_definitions\":%zu,"
+ "\"runtime_view_steps\":%zu,\"write_step\":%zu,\"reply_step\":%zu,\"prepared_program_bytes\":%zu,\"steps\":[",
+ p->read.to_end ? "true" : "false", p->read.offset, p->read.length, p->read_required,
+ p->write.to_end ? "true" : "false", p->write.offset, p->write.length, p->input_required,
+ p->reply_input ? "true" : "false", p->view_definitions, p->range_definitions,
+ p->input_steps, p->write_step, p->reply_step, sizeof(*p));
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ printf("%s{\"source_step\":%zu,\"source\":{\"offset\":%zu,\"length\":%zu,\"to_end\":%s},"
+ "\"offset\":{\"value\":%zu,\"from_u32le\":%s},\"length\":{\"value\":%zu,\"from_u32le\":%s}}",
+ i ? "," : "", step->source_step, step->source.offset, step->source.length,
+ step->source.to_end ? "true" : "false", step->offset.value, step->offset.from_u32le ? "true" : "false",
+ step->length.value, step->length.from_u32le ? "true" : "false");
+ }
+ printf("],\"write_effect\":\"%s\",\"splice_offset\":{\"value\":%zu,\"from_u32le\":%s},"
+ "\"splice_remove\":{\"value\":%zu,\"from_u32le\":%s}}\n",
+ p->splice ? "splice" : "write", p->splice_offset.value,
+ p->splice_offset.from_u32le ? "true" : "false", p->splice_remove.value,
+ p->splice_remove.from_u32le ? "true" : "false");
+ return 0;
+ }
+ if (pure_store_init(server.path) != PURE_OK) { fputs("Cannot initialize byte store directory\n", stderr); return 1; }
+ if (!pure_runtime_init(&server.runtime, server.work, SLOTS, &server.program,
+ pure_store_host(server.path), server.budget)) return 1;
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, stop_server);
+ signal(SIGTERM, stop_server);
+ int listener = socket(AF_INET, SOCK_STREAM, 0);
+ if (listener < 0) { perror("socket"); return 1; }
+ int one = 1;
+ setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ struct sockaddr_in address = {.sin_family = AF_INET, .sin_port = htons((uint16_t)port),
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ if (bind(listener, (struct sockaddr *)&address, sizeof(address)) || listen(listener, SLOTS) || !nonblocking(listener)) {
+ perror("listen"); close(listener); return 1;
+ }
+ socklen_t address_size = sizeof(address);
+ if (getsockname(listener, (struct sockaddr *)&address, &address_size)) { close(listener); return 1; }
+ for (size_t i = 0; i < SLOTS; ++i) server.connections[i].fd = -1;
+ printf("{\"port\":%u,\"storage\":\"immutable-byte-extents-v1\"}\n", ntohs(address.sin_port));
+ fflush(stdout);
+ while (!stopping) {
+ struct pollfd polls[SLOTS + 1] = {{.fd = server.active < SLOTS ? listener : -1, .events = POLLIN}};
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ polls[i + 1] = (struct pollfd){.fd = c->fd, .events = c->phase == WRITING ? POLLOUT : POLLIN};
+ }
+ int ready = poll(polls, SLOTS + 1, 50);
+ if (ready < 0 && errno != EINTR) { perror("poll"); stopping = 1; }
+ uint64_t now = now_ms();
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ if (c->fd < 0) continue;
+ if (now >= c->deadline) { ++server.expired; close_connection(c); continue; }
+ short events = polls[i + 1].revents;
+ if (events & (POLLERR | POLLNVAL)) { close_connection(c); continue; }
+ if (events & (POLLIN | POLLOUT | POLLHUP)) {
+ if (c->phase == WRITING) write_connection(c); else read_connection(c);
+ }
+ }
+ if (!stopping && (polls[0].revents & POLLIN)) {
+ int fd = accept(listener, NULL, NULL);
+ if (fd < 0) continue;
+ if (!nonblocking(fd)) { close(fd); continue; }
+ if (server.send_buffer) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &server.send_buffer, sizeof(server.send_buffer));
+ for (size_t i = 0; i < SLOTS; ++i) if (server.connections[i].fd < 0) {
+ server.connections[i] = (Connection){.fd = fd, .server = &server, .deadline = now_ms() + server.timeout_ms};
+ ++server.active;
+ ++server.accepted;
+ if (server.active > server.peak_active) server.peak_active = server.active;
+ break;
+ }
+ }
+ }
+ close(listener);
+ pure_runtime_stop(&server.runtime);
+ for (size_t i = 0; i < SLOTS; ++i) close_connection(&server.connections[i]);
+ fprintf(stderr, "{\"active\":%zu,\"retained_payload_bytes\":%zu,\"peak_retained_payload_bytes\":%zu,"
+ "\"payload_budget\":%zu,\"peak_connections\":%zu,\"accepted\":%" PRIu64 ",\"commits\":%" PRIu64 ","
+ "\"gets\":%" PRIu64 ",\"conflicts\":%" PRIu64 ",\"budget_rejections\":%" PRIu64 ","
+ "\"expired\":%" PRIu64 ",\"releases\":%" PRIu64 ",\"ingress_prefix_copy_bytes\":%" PRIu64 ","
+ "\"borrowed_output_bytes\":%" PRIu64 ",\"server_structure_bytes\":%zu}\n",
+ server.active, server.runtime.retained, server.runtime.peak_retained, server.budget, server.peak_active,
+ server.accepted, server.runtime.commits, server.runtime.gets, server.runtime.conflicts, server.runtime.budget_rejections,
+ server.expired, server.runtime.releases, server.prefix_copy_bytes, server.runtime.borrowed_output_bytes, sizeof(server));
+ return 0;
+usage:
+ fputs("pure-connections --program FILE --store DIRECTORY [--port 8767] [--budget BYTES] [--timeout-ms 10000] [--send-buffer BYTES]\n"
+ "pure-connections --check-program FILE\n", stderr);
+ return 2;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store-port.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store-port.c
new file mode 100644
index 0000000..9860308
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store-port.c
@@ -0,0 +1,44 @@
+#include "store-port.h"
+#include "store.h"
+#include <stdlib.h>
+#include <sys/mman.h>
+
+static void free_memory(void *data, size_t size) { (void)size; free(data); }
+static void unmap_memory(void *data, size_t size) { if (size) munmap(data, size); }
+
+static bool allocate(void *context, size_t size, PureResource *out) {
+ (void)context;
+ void *data = malloc(size);
+ if (!data) return false;
+ *out = (PureResource){.body = {data, size}, .allocation = data,
+ .allocation_size = size, .release = free_memory};
+ return true;
+}
+
+static PureResult read_value(void *context, const char *key, PureRegion region,
+ size_t minimum, size_t available, PureResource *out, int64_t *revision) {
+ PureStoredView view = {0};
+ PureResult result = pure_store_select(context, key, region.offset, region.length,
+ region.to_end, minimum, available, &view);
+ if (result == PURE_OK) {
+ *out = (PureResource){.body = view.body, .allocation = view.mapping,
+ .allocation_size = view.mapped_size, .release = view.mapped_size ? unmap_memory : NULL};
+ *revision = view.revision;
+ }
+ return result;
+}
+
+static PureResult write_value(void *context, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ return pure_store_put(context, key, expected, body, revision);
+}
+
+static PureResult splice_value(void *context, const char *key, int64_t expected,
+ size_t offset, size_t remove, PureSpan insert, int64_t *revision) {
+ return pure_store_splice(context, key, expected, offset, remove, insert, revision);
+}
+
+PureHost pure_store_host(const char *path) {
+ return (PureHost){.context = (void *)path, .allocate = allocate,
+ .read = read_value, .write = write_value, .splice = splice_value};
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store-port.h b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store-port.h
new file mode 100644
index 0000000..4c0d49d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store-port.h
@@ -0,0 +1,6 @@
+#ifndef PURE_STORE_PORT_H
+#define PURE_STORE_PORT_H
+#include "runtime.h"
+/* The path remains alive for the domain's complete lifetime, including pins. */
+PureHost pure_store_host(const char *path);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store.c
new file mode 100644
index 0000000..4c8bdc4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store.c
@@ -0,0 +1,258 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Immutable extent envelope: marker, little-endian u64 revision and payload
+ * length, then unchanged caller bytes. Single-threaded control API; cooperating
+ * processes serialize publication using .writer.lock. */
+enum { HEADER_BYTES = 24 };
+static const unsigned char magic[8] = {'P','U','R','E','B','0','0','1'};
+static uint64_t temporary_sequence;
+
+static bool fault(PureStoreStage stage) {
+#ifdef PURE_STORE_TEST
+ if (pure_store_test_fault(stage)) { errno = EIO; return true; }
+#else
+ (void)stage;
+#endif
+ return false;
+}
+
+static bool file_name(const char *key, char name[72]) {
+ if (!key) return false;
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ snprintf(name, 72, "obj-%s", key);
+ return true;
+}
+
+static uint64_t decode64(const unsigned char *bytes) {
+ uint64_t value = 0;
+ for (unsigned i = 0; i < 8; ++i) value |= (uint64_t)bytes[i] << (8 * i);
+ return value;
+}
+
+static void encode64(unsigned char *bytes, uint64_t value) {
+ for (unsigned i = 0; i < 8; ++i) bytes[i] = (unsigned char)(value >> (8 * i));
+}
+
+static bool sync_fd(int fd) {
+ int rc;
+ do { rc = fsync(fd); } while (rc && errno == EINTR);
+ return rc == 0;
+}
+
+static bool write_bytes(int fd, const unsigned char *bytes, size_t length) {
+ while (length) {
+ ssize_t n = write(fd, bytes, length);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ bytes += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static bool read_header(int fd, int64_t *revision, size_t *length) {
+ struct stat info;
+ if (fstat(fd, &info) || !S_ISREG(info.st_mode)) return false;
+ unsigned char header[HEADER_BYTES];
+ size_t used = 0;
+ while (used < sizeof(header)) {
+ ssize_t n = pread(fd, header + used, sizeof(header) - used, (off_t)used);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ used += (size_t)n;
+ }
+ uint64_t version = decode64(header + 8), size = decode64(header + 16);
+ if (memcmp(header, magic, sizeof(magic)) || !version || version > INT64_MAX ||
+ size > PURE_OBJECT_LIMIT || info.st_size != (off_t)(HEADER_BYTES + size)) return false;
+ *revision = (int64_t)version;
+ *length = (size_t)size;
+ return true;
+}
+
+PureResult pure_store_init(const char *path) {
+ if (!path || !*path) return PURE_STORE_ERROR;
+ bool created = mkdir(path, 0700) == 0;
+ if (!created && errno != EEXIST) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR; /* Never reinterpret an old DB file. */
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600);
+ struct stat info;
+ bool ok = lock >= 0 && fstat(lock, &info) == 0 && S_ISREG(info.st_mode) && sync_fd(lock);
+ if (lock >= 0) close(lock);
+ if (ok) ok = sync_fd(directory);
+ close(directory);
+ if (!ok) return PURE_STORE_ERROR;
+ if (created) {
+ char *parent = strdup(path);
+ if (!parent) return PURE_STORE_ERROR;
+ size_t length = strlen(parent);
+ while (length > 1 && parent[length - 1] == '/') parent[--length] = 0;
+ char *slash = strrchr(parent, '/');
+ if (!slash) strcpy(parent, ".");
+ else if (slash == parent) parent[1] = 0;
+ else *slash = 0;
+ int fd = open(parent, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ free(parent);
+ ok = fd >= 0 && sync_fd(fd);
+ if (fd >= 0) close(fd);
+ }
+ return ok ? PURE_OK : PURE_STORE_ERROR;
+}
+
+void pure_store_release(PureStoredView *view) {
+ if (view->mapped_size) munmap(view->mapping, view->mapped_size);
+ *view = (PureStoredView){0};
+}
+
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out) {
+ *out = (PureStoredView){0};
+ char name[72];
+ if (!file_name(key, name)) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ int cause = errno;
+ close(directory);
+ if (fd < 0) return cause == ENOENT ? PURE_NOT_FOUND : PURE_STORE_ERROR;
+ int64_t revision;
+ size_t size;
+ PureResult result = PURE_STORE_ERROR;
+ if (!read_header(fd, &revision, &size)) goto finish;
+ if (size < minimum) { result = PURE_LIMIT; goto finish; }
+ if (offset > size) { result = PURE_LIMIT; goto finish; }
+ if (whole) length = size - offset;
+ if (offset > size || length > size - offset) { result = PURE_LIMIT; goto finish; }
+ if (length > available) { result = PURE_BUDGET; goto finish; }
+ if (length) {
+ long page = sysconf(_SC_PAGESIZE);
+ if (page <= 0) goto finish;
+ size_t start = HEADER_BYTES + offset;
+ size_t aligned = start - start % (size_t)page;
+ size_t prefix = start - aligned;
+ size_t mapped_size = prefix + length;
+ void *mapping = mmap(NULL, mapped_size, PROT_READ, MAP_PRIVATE, fd, (off_t)aligned);
+ if (mapping == MAP_FAILED) goto finish;
+ out->mapping = mapping;
+ out->mapped_size = mapped_size;
+ out->body = (PureSpan){(const unsigned char *)mapping + prefix, length};
+ }
+ out->revision = revision;
+ out->object_size = size;
+ result = PURE_OK;
+finish:
+ close(fd); /* The mapping retains this immutable file version after rename. */
+ return result;
+}
+
+PureResult pure_store_get(const char *path, const char *key, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, 0, 0, true, 0, available, out);
+}
+
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, offset, length, false, 0, available, out);
+}
+
+static bool copy_extent(int source, int destination, size_t offset, size_t length) {
+ unsigned char scratch[4096];
+ while (length) {
+ size_t wanted = length < sizeof(scratch) ? length : sizeof(scratch);
+ ssize_t n = pread(source, scratch, wanted, (off_t)(HEADER_BYTES + offset));
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0 || !write_bytes(destination, scratch, (size_t)n)) return false;
+ offset += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static PureResult mutate(const char *path, const char *key, int64_t expected,
+ PureSpan body, bool splice, size_t offset, size_t remove, int64_t *revision) {
+ *revision = 0;
+ char name[72], temporary[96] = "";
+ if (!file_name(key, name) || (body.size && !body.data)) return PURE_STORE_ERROR;
+ if (body.size > PURE_OBJECT_LIMIT || expected < 0) return PURE_LIMIT;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_NOFOLLOW | O_CLOEXEC);
+ int fd = -1, source = -1;
+ size_t old_size = 0, result_size = body.size;
+ PureResult result = PURE_STORE_ERROR;
+ struct stat info;
+ if (lock < 0 || fstat(lock, &info) || !S_ISREG(info.st_mode)) goto finish;
+ struct flock hold = {.l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0};
+ if (fcntl(lock, F_SETLK, &hold)) {
+ if (errno == EACCES || errno == EAGAIN) result = PURE_BUSY;
+ goto finish;
+ }
+ source = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (source >= 0) {
+ if (!read_header(source, revision, &old_size)) goto finish;
+ } else if (errno != ENOENT) goto finish;
+ if (*revision != expected) { result = PURE_CONFLICT; goto finish; }
+ if (*revision == INT64_MAX) { result = PURE_LIMIT; goto finish; }
+ if (splice) {
+ if (offset > old_size || remove > old_size - offset ||
+ body.size > PURE_OBJECT_LIMIT - (old_size - remove)) { result = PURE_LIMIT; goto finish; }
+ result_size = old_size - remove + body.size;
+ }
+ for (unsigned attempt = 0; attempt < 64; ++attempt) {
+ if (temporary_sequence == UINT64_MAX) goto finish;
+ snprintf(temporary, sizeof(temporary), ".pending-%ld-%" PRIu64, (long)getpid(), ++temporary_sequence);
+ fd = openat(directory, temporary, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
+ if (fd >= 0) break;
+ temporary[0] = 0; /* Never remove an existing file on a name collision. */
+ if (errno != EEXIST) goto finish;
+ }
+ if (fd < 0) goto finish;
+ unsigned char header[HEADER_BYTES];
+ memcpy(header, magic, sizeof(magic));
+ encode64(header + 8, (uint64_t)*revision + 1);
+ encode64(header + 16, result_size);
+ if (!write_bytes(fd, header, sizeof(header)) || fault(PURE_AFTER_HEADER)) goto finish;
+ if (splice && !copy_extent(source, fd, 0, offset)) goto finish;
+ if (!write_bytes(fd, body.data, body.size)) goto finish;
+ if (splice && !copy_extent(source, fd, offset + remove, old_size - offset - remove)) goto finish;
+ if (fault(PURE_BEFORE_FILE_SYNC) || !sync_fd(fd)) goto finish;
+ int close_result = close(fd);
+ fd = -1;
+ if (close_result || fault(PURE_BEFORE_RENAME) || renameat(directory, temporary, directory, name)) goto finish;
+ temporary[0] = 0; /* Published: a later sync failure does not roll it back. */
+ ++*revision;
+ result = fault(PURE_BEFORE_DIR_SYNC) || !sync_fd(directory) ? PURE_UNCERTAIN : PURE_OK;
+finish:
+ if (fd >= 0) close(fd);
+ if (source >= 0) close(source);
+ if (*temporary) unlinkat(directory, temporary, 0);
+ if (lock >= 0) close(lock);
+ close(directory);
+ return result;
+}
+
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ return mutate(path, key, expected, body, false, 0, 0, revision);
+}
+
+PureResult pure_store_splice(const char *path, const char *key, int64_t expected,
+ size_t offset, size_t remove, PureSpan insert, int64_t *revision) {
+ return mutate(path, key, expected, insert, true, offset, remove, revision);
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store.h b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store.h
new file mode 100644
index 0000000..99a3ef5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/store.h
@@ -0,0 +1,44 @@
+#ifndef PURE_STORE_H
+#define PURE_STORE_H
+#include "flow.h"
+#include "result.h"
+#include <stdint.h>
+
+#define PURE_OBJECT_LIMIT ((2u * 6u + 32u) * 32768u + 8192u)
+typedef struct {
+ void *mapping;
+ size_t mapped_size, object_size;
+ PureSpan body;
+ int64_t revision;
+} PureStoredView;
+
+PureResult pure_store_init(const char *path);
+PureResult pure_store_get(const char *path, const char *key, size_t available,
+ PureStoredView *out);
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out);
+/* Inspect once: guards and mapping refer to the same immutable file version.
+ * minimum preserves bounds checks from eliminated intermediate views.
+ * whole selects the suffix starting at offset; otherwise length is exact. */
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out);
+void pure_store_release(PureStoredView *);
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision);
+/* Atomic byte replacement: retain [0,offset), insert bytes, retain suffix after
+ * remove bytes. Check the expected revision and bounds under the same writer
+ * lock. expected=0 permits creating an empty base (offset=remove=0).
+ * Streams retained bytes through bounded scratch space; never assembles a
+ * whole new object in application memory. Still rewrites the immutable file. */
+PureResult pure_store_splice(const char *path, const char *key, int64_t expected,
+ size_t offset, size_t remove, PureSpan insert, int64_t *revision);
+
+/* Fault hooks exist only in the separately built unit-test binary. */
+typedef enum {
+ PURE_AFTER_HEADER, PURE_BEFORE_FILE_SYNC, PURE_BEFORE_RENAME, PURE_BEFORE_DIR_SYNC
+} PureStoreStage;
+#ifdef PURE_STORE_TEST
+int pure_store_test_fault(PureStoreStage stage);
+#endif
+#endif
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-fields.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-fields.c
new file mode 100644
index 0000000..63dfc3e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-fields.c
@@ -0,0 +1,153 @@
+#include "program.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static const char layout[] = "layout Envelope { marker: bytes[1]; start: u32le; count: u32le; text: bytes; }";
+static PureProgram parse(const char *source) {
+ PureProgram p;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &p, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return p;
+}
+static void invalid(const char *source) {
+ PureProgram p;
+ memset(&p, 0x5a, sizeof(p));
+ unsigned char before[sizeof(p)];
+ memcpy(before, &p, sizeof(p));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(*error && !memcmp(before, &p, sizeof(p)));
+}
+static void encode(unsigned char *at, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) at[i] = (unsigned char)(value >> (8 * i));
+}
+int main(void) {
+ char source[8000];
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let alias = input; let start = alias.start; let text = alias.text; "
+ "let selected = range(text, start, alias.count); let result = selected; "
+ "let saved = store.write(request.key, request.revision, result); reply(saved, selected); }", layout, get);
+ PureProgram p = parse(source);
+ CHECK(p.input_steps == 1 && p.input_required == 9 && p.write_step == 1 && p.reply_step == 1);
+ CHECK(p.steps[0].source.offset == 9 && p.steps[0].source.to_end);
+ CHECK(p.steps[0].offset.value == 1 && p.steps[0].offset.from_u32le);
+ CHECK(p.steps[0].length.value == 5 && p.steps[0].length.from_u32le);
+ unsigned char bytes[609];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 13);
+ PureSpan stored, returned;
+ for (size_t n = 0; n < 9; ++n) {
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, n}, &stored, &returned));
+ CHECK(!stored.size && !returned.size);
+ }
+ const uint32_t offsets[] = {0, 1, 255, 257, 599, 600, 601, UINT32_MAX};
+ const uint32_t counts[] = {0, 1, 2, 260, 600, UINT32_MAX};
+ size_t comparisons = 0;
+ for (size_t i = 0; i < sizeof(offsets) / sizeof(*offsets); ++i)
+ for (size_t j = 0; j < sizeof(counts) / sizeof(*counts); ++j) {
+ uint32_t start = offsets[i], count = counts[j];
+ encode(bytes + 1, start);
+ encode(bytes + 5, count);
+ bool expected = start <= 600 && count <= 600 - start;
+ CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned) == expected);
+ if (expected) {
+ CHECK(stored.size == count && returned.size == count && stored.data == returned.data);
+ CHECK(!count || stored.data == bytes + 9 + start);
+ } else CHECK(!stored.size && !returned.size);
+ ++comparisons;
+ }
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let first = range(input.text, input.start, input.count); let second = range(first, 1, 2); "
+ "let saved = store.write(request.key, request.revision, second); reply(saved, second); }", layout, get);
+ p = parse(source);
+ CHECK(p.input_steps == 2 && p.steps[1].source_step == 1);
+ encode(bytes + 1, 3); encode(bytes + 5, 4);
+ CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+ CHECK(stored.size == 2 && stored.data == bytes + 13);
+ encode(bytes + 5, 2);
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let unused = range(input.text, input.start, input.count); "
+ "let saved = store.write(request.key, request.revision, input.text); reply(saved); }", layout, get);
+ p = parse(source);
+ encode(bytes + 1, UINT32_MAX);
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+
+ snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); "
+ "let input = view(Envelope, o.body); reply(o, input.text); } %s", layout, put);
+ p = parse(source);
+ CHECK(p.read.to_end && p.read.offset == 9 && p.read_required == 9 && !p.input_steps);
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let selection = range(input.text, 2, 3); let saved = store.write(request.key, request.revision, selection); reply(saved); }", layout, get);
+ p = parse(source);
+ CHECK(!p.input_steps && p.write.offset == 11 && p.write.length == 3 && p.input_required == 14);
+ snprintf(source, sizeof(source), "layout Empty { body: bytes; } %s on put { let input = view(Empty, request.body); "
+ "let saved = store.write(request.key, request.revision, input.body); reply(saved, input.body); }", get);
+ p = parse(source);
+ CHECK(pure_program_input(&p, (PureSpan){0}, &stored, &returned) && !stored.size && !returned.size);
+
+ const char *bad_layout[] = {
+ "layout E {}", "layout E { x: bytes; y: u32le; }", "layout E { x: u32le; x: bytes; }",
+ "layout E { x: bytes[1449985]; }", "layout E { x: bytes[1449984]; y: u32le; }",
+ "layout E { x: bytes[184467440737095516160]; }", "layout E { x: u64le; }",
+ "layout E { x: u32le; } layout E { y: bytes; }"
+ };
+ for (size_t i = 0; i < sizeof(bad_layout) / sizeof(*bad_layout); ++i) {
+ snprintf(source, sizeof(source), "%s %s %s", bad_layout[i], get, put); invalid(source);
+ }
+ const char *bad_input[] = {
+ "let input = view(Missing, request.body);",
+ "let input = view(Envelope, request.body); let x = input.missing;",
+ "let input = view(Envelope, request.body); let x = range(input.text, input.text, 1);",
+ "let short = range(request.body, 0, 8); let input = view(Envelope, short);",
+ "let input = view(Envelope, request.body); let x = range(input.text, input.start, 20); let y = view(Envelope, x);"
+ };
+ for (size_t i = 0; i < sizeof(bad_input) / sizeof(*bad_input); ++i) {
+ snprintf(source, sizeof(source), "%s %s on put { %s let saved = store.write(request.key, request.revision, request.body); reply(saved); }", layout, get, bad_input[i]);
+ invalid(source);
+ }
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let saved = store.write(request.key, request.revision, input.start); reply(saved); }", layout, get);
+ invalid(source);
+ snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); let input = view(Envelope, o.body); "
+ "let x = range(input.text, input.start, input.count); reply(o, x); } %s", layout, put);
+ invalid(source);
+ for (size_t count = 8; count <= 9; ++count) {
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); ", layout, get);
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let v%zu = range(input.text, input.start, input.count); ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let saved = store.write(request.key, request.revision, input.text); reply(saved); }");
+ if (count == 8) CHECK(parse(source).input_steps == 8); else invalid(source);
+ }
+ for (size_t count = 4; count <= 5; ++count) {
+ source[0] = 0;
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "layout L%zu { body: bytes; } ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "%s %s", get, put);
+ if (count == 4) (void)parse(source); else invalid(source);
+ }
+ for (size_t count = 16; count <= 17; ++count) {
+ strcpy(source, "layout L { ");
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "f%zu: u32le; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "} %s %s", get, put);
+ if (count == 16) (void)parse(source); else invalid(source);
+ }
+ printf("{\"fields\":\"named-layouts-unaligned-u32le-tail-dynamic-ranges-aliases-failures-limits\","
+ "\"data_boundary_cases\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-flow.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-flow.c
new file mode 100644
index 0000000..5ff028d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-flow.c
@@ -0,0 +1,183 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static int failed_stage = -1;
+static bool crash_at_stage;
+int pure_store_test_fault(PureStoreStage stage) {
+ if ((int)stage != failed_stage) return 0;
+ if (crash_at_stage) _exit(77);
+ return 1;
+}
+typedef struct { unsigned char *bytes; unsigned releases; } Owner;
+static void release(void *raw) {
+ Owner *owner = raw;
+ free(owner->bytes);
+ owner->bytes = NULL;
+ ++owner->releases;
+}
+
+static void transfers(void) {
+ Owner owner = {.bytes = malloc(5)};
+ CHECK(owner.bytes);
+ memcpy(owner.bytes, "a\0bcd", 5);
+ PureTransfer transfer = {0};
+ pure_transfer_init(&transfer, (PureSpan){(const unsigned char *)"head", 4},
+ (PureSpan){owner.bytes, 5}, &owner, release);
+ CHECK(!pure_transfer_consume(&transfer, 5));
+ CHECK(transfer.active && !owner.releases);
+ CHECK(pure_transfer_consume(&transfer, 0));
+ unsigned char received[9];
+ size_t used = 0;
+ while (transfer.active) {
+ PureSpan span = pure_transfer_next(&transfer, 2);
+ CHECK(span.size && span.size <= 2);
+ memcpy(received + used, span.data, span.size);
+ used += span.size;
+ CHECK(pure_transfer_consume(&transfer, span.size));
+ CHECK((used == 9) == (owner.releases == 1));
+ }
+ CHECK(used == 9 && !memcmp(received, "heada\0bcd", 9));
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 1 && !pure_transfer_consume(&transfer, 0));
+ owner.bytes = malloc(3);
+ CHECK(owner.bytes);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){owner.bytes, 3}, &owner, release);
+ CHECK(pure_transfer_consume(&transfer, 1));
+ pure_transfer_abort(&transfer);
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 2 && !transfer.active);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){0}, &owner, release);
+ CHECK(owner.releases == 3 && !transfer.active);
+}
+
+static void storage(const char *path) {
+ CHECK(pure_store_init(path) == PURE_OK);
+ PureStoredView first, second;
+ CHECK(pure_store_get(path, "missing", 100, &first) == PURE_NOT_FOUND);
+ CHECK(!first.mapping && !first.mapped_size);
+ static const unsigned char original[] = {0, 1, 2, 255, 17};
+ static const unsigned char updated[] = {9, 8, 7};
+ int64_t revision;
+ CHECK(pure_store_put(path, "work", 0, (PureSpan){original, sizeof(original)}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ CHECK(pure_store_get(path, "work", sizeof(original) - 1, &first) == PURE_BUDGET);
+ CHECK(!first.mapping && !first.mapped_size);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 3, &first) == PURE_OK);
+ CHECK(first.object_size == sizeof(original) && first.body.size == 3 && !memcmp(first.body.data, original + 1, 3));
+ pure_store_release(&first);
+ CHECK(pure_store_get_range(path, "work", SIZE_MAX, 1, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, SIZE_MAX, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 2, &first) == PURE_BUDGET);
+ CHECK(pure_store_get_range(path, "work", sizeof(original), 0, 0, &first) == PURE_OK);
+ CHECK(!first.mapped_size && !first.body.size);
+ pure_store_release(&first);
+ CHECK(pure_store_get(path, "work", sizeof(original), &first) == PURE_OK);
+ CHECK(first.body.size == sizeof(original) && first.revision == 1);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 2);
+ CHECK(!memcmp(first.body.data, original, sizeof(original)));
+ CHECK(pure_store_get(path, "work", 100, &second) == PURE_OK);
+ CHECK(second.revision == 2 && second.body.size == sizeof(updated));
+ CHECK(!memcmp(second.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ pure_store_release(&first);
+ pure_store_release(&second);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){original, sizeof(original)}, &revision) == PURE_CONFLICT);
+ CHECK(revision == 2);
+
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 2 && !memcmp(first.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == 3);
+ failed_stage = -1;
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_CONFLICT);
+
+ /* A crashed unpublished writer leaves only a private file. A new publisher
+ * must still use the previous committed version, never an incomplete body. */
+ pid_t child = fork();
+ CHECK(child >= 0);
+ if (!child) {
+ failed_stage = PURE_AFTER_HEADER;
+ crash_at_stage = true;
+ pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision);
+ _exit(78);
+ }
+ int status;
+ CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 77);
+ CHECK(pure_store_init(path) == PURE_OK);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 4);
+
+ char file[320];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ CHECK(fd >= 0);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_put(path, "work", INT64_MAX, (PureSpan){original, sizeof(original)}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_put(path, "empty", 0, (PureSpan){0}, &revision) == PURE_OK);
+ CHECK(pure_store_get(path, "empty", 0, &first) == PURE_OK && first.body.size == 0);
+ pure_store_release(&first);
+
+ /* Range mapping crosses page boundaries without copying a whole object. */
+ long page = sysconf(_SC_PAGESIZE);
+ CHECK(page >= 128 && (size_t)page <= PURE_OBJECT_LIMIT / 3);
+ size_t size = (size_t)page * 3, offset = (size_t)page + 13, length = (size_t)page + 105;
+ unsigned char *bytes = malloc(size);
+ CHECK(bytes);
+ for (size_t i = 0; i < size; ++i) bytes[i] = (unsigned char)((i * 17u) ^ (i >> 8) ^ (i >> 16));
+ CHECK(pure_store_put(path, "range", 0, (PureSpan){bytes, size}, &revision) == PURE_OK);
+ CHECK(pure_store_get_range(path, "range", offset, length, length, &first) == PURE_OK);
+ CHECK(first.body.size == length && !memcmp(first.body.data, bytes + offset, length));
+ pure_store_release(&first);
+ free(bytes);
+ snprintf(file, sizeof(file), "%s/obj-broken", path);
+ fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0600);
+ CHECK(fd >= 0 && write(fd, "incomplete", 10) == 10 && close(fd) == 0);
+ CHECK(pure_store_get(path, "broken", 100, &first) == PURE_STORE_ERROR && !first.mapped_size);
+ CHECK(pure_store_put(path, "broken", 0, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_init(file) == PURE_STORE_ERROR);
+ struct stat info;
+ CHECK(stat(file, &info) == 0 && info.st_size == 10);
+}
+
+int main(void) {
+ transfers();
+ char directory[] = "/tmp/pure-connection-unit-XXXXXX";
+ CHECK(mkdtemp(directory));
+ char path[256];
+ snprintf(path, sizeof(path), "%s/store", directory);
+ storage(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ CHECK(rmdir(directory) == 0);
+ puts("{\"transfer\":\"partial-consumption-and-single-release\","
+ "\"storage\":\"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty\"}");
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-program.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-program.c
new file mode 100644
index 0000000..6a4a19d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-program.c
@@ -0,0 +1,111 @@
+#include "program.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static PureProgram parse(const char *source) {
+ PureProgram program;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &program, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return program;
+}
+static void invalid(const char *source) {
+ PureProgram program;
+ memset(&program, 0x5a, sizeof(program));
+ unsigned char original[sizeof(program)];
+ memcpy(original, &program, sizeof(program));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &program, error, sizeof(error)));
+ CHECK(*error && !memcmp(original, &program, sizeof(program)));
+}
+int main(void) {
+ char source[4096];
+ snprintf(source, sizeof(source), "%s %s", get, put);
+ PureProgram plan = parse(source);
+ CHECK(plan.read.to_end && plan.write.to_end && !plan.reply_input);
+ CHECK(!plan.view_definitions && !plan.read_required && !plan.input_required);
+ snprintf(source, sizeof(source), "%s on put { let a = range(request.body, 2, 10); "
+ "let b = range(a, 3, 4); let alias = b; "
+ "let saved = store.write(request.key, request.revision, alias); reply(saved, b); }", get);
+ plan = parse(source);
+ CHECK(plan.write.offset == 5 && plan.write.length == 4 && !plan.write.to_end);
+ CHECK(plan.reply.offset == 5 && plan.reply.length == 4 && plan.reply_input);
+ CHECK(plan.input_required == 12 && plan.range_definitions == 2 && plan.view_definitions == 3);
+ /* Ordered reference views keep even unused bounds failures observable. */
+ unsigned char bytes[160];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 7);
+ size_t comparisons = 0;
+ for (size_t a = 0; a < 4; ++a) for (size_t b = 0; b < 6; ++b)
+ for (size_t c = 0; c <= b; ++c) for (size_t d = 0; d <= b - c; ++d) {
+ size_t unused_end = (a + b + c) % 12;
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); "
+ "let unused = range(o.body, %zu, 0); let first = range(o.body, %zu, %zu); "
+ "let second = range(first, %zu, %zu); reply(o, second); } %s",
+ unused_end, a, b, c, d, put);
+ plan = parse(source);
+ for (size_t n = 0; n < 16; ++n) {
+ bool reference_ok = unused_end <= n && a <= n && b <= n - a;
+ PureSpan selected;
+ bool prepared_ok = n >= plan.read_required &&
+ pure_region_span(plan.read, (PureSpan){bytes, n}, &selected);
+ CHECK(reference_ok == prepared_ok);
+ if (reference_ok) {
+ CHECK(selected.size == d);
+ CHECK(!d || !memcmp(selected.data, bytes + a + c, d));
+ }
+ ++comparisons;
+ }
+ }
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); reply(o); } %s", put);
+ plan = parse(source);
+ CHECK(!plan.read.to_end && !plan.read.length);
+ const char *bad_get[] = {
+ "on get { let o = store.read(request.key); let x = range(o.body, 0, 2); let y = range(x, 2, 1); reply(o, y); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 184467440737095516160, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 1449984, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let o = o.body; reply(o); }",
+ "on get { let o = store.read(request.key); let x = x; reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = store.read(request.key); reply(x); }",
+ "on get { let o = store.read(request.key); reply(o, request.body); }",
+ "on get { let o = store.read(request.key); let x = o.body; reply(x); }",
+ "on get { let o = store.read(request.key); reply(o.body); }",
+ "on get { let o = store.read(request.key); reply(o); let x = o.body; }",
+ "on get { let o = store.read(request.key); reply(o);", "on get {}"
+ };
+ for (size_t i = 0; i < sizeof(bad_get) / sizeof(*bad_get); ++i) {
+ snprintf(source, sizeof(source), "%s %s", bad_get[i], put); invalid(source);
+ }
+ const char *bad_put[] = {
+ "on put { let s = store.write(request.key, request.revision, request.body); let b = range(request.body, 0, 1); reply(s, b); }",
+ "on put { let s = store.write(request.key, request.revision, request.body); reply(s, s.body); }",
+ "on put { let s = store.read(request.key); reply(s); }"
+ };
+ for (size_t i = 0; i < sizeof(bad_put) / sizeof(*bad_put); ++i) {
+ snprintf(source, sizeof(source), "%s %s", get, bad_put[i]); invalid(source);
+ }
+ invalid(get);
+ snprintf(source, sizeof(source), "%s %s %s", get, get, put); invalid(source);
+ snprintf(source, sizeof(source), "%s %s garbage", get, put); invalid(source);
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); ");
+ for (size_t i = 0; i < 32; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let x%zu = o.body; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "reply(o); } %s", put); invalid(source);
+ char oversized[PURE_PROGRAM_LIMIT + 1];
+ memset(oversized, ' ', sizeof(oversized));
+ char error[160];
+ CHECK(!pure_program_parse(oversized, sizeof(oversized), &plan, error, sizeof(error)));
+ const char embedded[] = "on get\0{}";
+ CHECK(!pure_program_parse(embedded, sizeof(embedded) - 1, &plan, error, sizeof(error)));
+ PureSpan selected;
+ CHECK(pure_region_span((PureRegion){0}, (PureSpan){0}, &selected) && !selected.data && !selected.size);
+ printf("{\"program\":\"prepare-views-preserve-guards-types-effects-and-atomic-install\","
+ "\"boundary_semantic_comparisons\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-runtime.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-runtime.c
new file mode 100644
index 0000000..0ff6a8b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-runtime.c
@@ -0,0 +1,285 @@
+#define _POSIX_C_SOURCE 200809L
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const PureProgram identity = {
+ .read = {.to_end = true}, .write = {.to_end = true},
+ .reply = {.to_end = true}, .reply_input = true
+};
+typedef struct {
+ size_t allocations, writes, frees, live;
+ bool allocation_failure, oversized_read, reenter;
+ PureRuntime *runtime;
+ unsigned char received[256];
+ size_t received_size;
+} Host;
+typedef struct { Host *host; unsigned char bytes[]; } Allocation;
+
+static void free_input(void *pointer, size_t size) {
+ Allocation *a = pointer;
+ assert(size > 0 && a->host->live > 0);
+ ++a->host->frees;
+ --a->host->live;
+ free(a);
+}
+
+static bool allocate(void *context, size_t size, PureResource *out) {
+ Host *host = context;
+ if (host->allocation_failure) return false;
+ Allocation *a = malloc(sizeof(*a) + size);
+ assert(a);
+ a->host = host;
+ ++host->allocations;
+ ++host->live;
+ *out = (PureResource){.body = {a->bytes, size}, .allocation = a,
+ .allocation_size = size, .release = free_input};
+ return true;
+}
+
+static PureResult write_value(void *context, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ Host *host = context;
+ (void)key;
+ if (host->reenter) {
+ PureTicket ignored;
+ assert(pure_runtime_accept(host->runtime, PURE_INPUT_WRITE, "reenter", 0, 0, &ignored) == PURE_INVALID);
+ assert(!pure_runtime_step(host->runtime));
+ }
+ if (expected == 99) { *revision = 1; return PURE_CONFLICT; }
+ ++host->writes;
+ assert(body.size <= sizeof(host->received));
+ if (body.size) memcpy(host->received, body.data, body.size);
+ host->received_size = body.size;
+ *revision = 1;
+ return PURE_OK;
+}
+
+static PureResult read_value(void *context, const char *key, PureRegion range,
+ size_t minimum, size_t available, PureResource *out, int64_t *revision) {
+ Host *host = context;
+ (void)key; (void)range; (void)minimum;
+ if (!host->oversized_read) return PURE_NOT_FOUND;
+ assert(available < 1000);
+ assert(allocate(host, available + 1, out));
+ *revision = 1;
+ return PURE_OK; /* Deliberately violates the available-credit contract. */
+}
+
+static PureHost port(Host *host) {
+ return (PureHost){.context = host, .allocate = allocate, .read = read_value, .write = write_value};
+}
+
+static PureTicket submit(PureRuntime *r, const char *key, const void *bytes, size_t length) {
+ PureTicket ticket;
+ assert(pure_runtime_accept(r, PURE_INPUT_WRITE, key, 0, length, &ticket) == PURE_OK);
+ size_t capacity;
+ unsigned char *input = pure_runtime_ingress(ticket, &capacity);
+ assert(capacity == length);
+ if (length) memcpy(input, bytes, length);
+ assert(pure_runtime_ready(ticket));
+ assert(!pure_runtime_ready(ticket));
+ return ticket;
+}
+
+static PureOutcome completed(PureRuntime *r, PureTicket ticket) {
+ PureOutcome result;
+ while (!pure_runtime_result(ticket, &result)) assert(pure_runtime_step(r));
+ return result;
+}
+
+static void admission_and_lifecycle(void) {
+ Host host = {0};
+ PureRuntime r;
+ PureWork work[3];
+ assert(pure_runtime_init(&r, work, 3, &identity, port(&host), 5));
+ host.runtime = &r;
+ PureTicket a, untouched = {0}, out = untouched;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "../bad", 0, 1, &out) == PURE_INVALID);
+ assert(!out.runtime && !host.allocations);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "a", 0, 4, &a) == PURE_OK);
+ assert(r.retained == 4 && !pure_runtime_step(&r) && !host.writes);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "b", 0, 2, &out) == PURE_BUDGET);
+ assert(!out.runtime && host.allocations == 1);
+ assert(pure_runtime_cancel(a));
+ PureOutcome cancelled;
+ assert(pure_runtime_result(a, &cancelled) && cancelled.status == PURE_CANCELLED);
+ assert(r.retained == 0 && host.frees == 1 && !pure_runtime_cancel(a));
+ assert(pure_runtime_release(a) && !pure_runtime_release(a));
+ assert(!pure_runtime_result(a, &cancelled));
+
+ PureTicket first = submit(&r, "first", "1", 1);
+ PureTicket middle = submit(&r, "middle", "2", 1);
+ PureTicket last = submit(&r, "last", "3", 1);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "full", 0, 0, &out) == PURE_BUSY);
+ assert(pure_runtime_cancel(middle));
+ assert(pure_runtime_release(middle));
+ pure_runtime_stop(&r);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "closed", 0, 0, &out) == PURE_CLOSED);
+ assert(!pure_runtime_restart(&r, &identity, port(&host), 5));
+ host.reenter = true;
+ assert(completed(&r, first).status == PURE_OK && host.received[0] == '1');
+ assert(completed(&r, last).status == PURE_OK && host.received[0] == '3');
+ assert(!pure_runtime_step(&r));
+ assert(pure_runtime_release(first) && pure_runtime_release(last));
+ assert(r.active == 0 && r.retained == 0 && host.live == 0);
+ assert(pure_runtime_restart(&r, &identity, port(&host), 5));
+ PureTicket next = submit(&r, "next", "4", 1);
+ assert(next.generation > last.generation && !pure_runtime_ready(a));
+ assert(!pure_runtime_release(last));
+ assert(pure_runtime_release(next)); /* queued input: no effect */
+ assert(host.writes == 2 && !pure_runtime_step(&r));
+
+ host.allocation_failure = true;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "no_memory", 0, 1, &out) == PURE_ALLOCATION);
+ assert(r.active == 0 && r.retained == 0);
+ host.allocation_failure = false;
+ PureHost denied = port(&host);
+ denied.write = NULL;
+ assert(pure_runtime_restart(&r, &identity, denied, 5));
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "denied", 0, 1, &out) == PURE_DENIED);
+ assert(pure_runtime_restart(&r, &identity, port(&host), 5));
+ host.oversized_read = true;
+ assert(pure_runtime_accept(&r, PURE_INPUT_READ, "bad_host", 0, 0, &out) == PURE_OK);
+ assert(completed(&r, out).status == PURE_BUDGET && host.live == 0 && r.retained == 0);
+ assert(pure_runtime_release(out));
+ r.serial = UINT64_MAX;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "exhausted", 0, 0, &out) == PURE_LIMIT);
+}
+
+static void forwarding(void) {
+ Host a = {0}, b = {0}, c = {0};
+ PureRuntime source, left, right;
+ PureWork source_work[1], left_work[1], right_work[1];
+ assert(pure_runtime_init(&source, source_work, 1, &identity, port(&a), 8));
+ assert(pure_runtime_init(&left, left_work, 1, &identity, port(&b), 2));
+ assert(pure_runtime_init(&right, right_work, 1, &identity, port(&c), 8));
+ PureTicket original = submit(&source, "original", "value", 5), x = {0}, y;
+ PureOutcome result = completed(&source, original);
+ assert(result.status == PURE_OK);
+ const unsigned char *backing = result.body.data;
+ assert(pure_runtime_forward(original, &left, "left", 0, &x) == PURE_BUDGET);
+ assert(!x.runtime && source.work[0].pins == 0);
+ assert(pure_runtime_restart(&left, &identity, port(&b), 8));
+ assert(pure_runtime_forward(original, &left, "left", 0, &x) == PURE_OK);
+ assert(pure_runtime_forward(original, &right, "right", 0, &y) == PURE_OK);
+ assert(pure_runtime_release(original));
+ assert(!pure_runtime_result(original, &result));
+ pure_runtime_stop(&source);
+ assert(!pure_runtime_restart(&source, &identity, port(&a), 8));
+ assert(a.live == 1 && !b.allocations && !c.allocations);
+ assert(pure_runtime_cancel(x) && pure_runtime_release(x));
+ assert(a.live == 1 && !b.writes);
+ result = completed(&right, y);
+ assert(result.body.data == backing && result.body.size == 5 && !memcmp(result.body.data, "value", 5));
+ assert(c.writes == 1 && !c.allocations && source.retained == 5);
+ assert(!pure_runtime_cancel(y)); /* effects cannot be rolled back */
+ assert(pure_runtime_release(y));
+ assert(a.frees == 1 && !source.active && !source.retained && !right.active && !right.retained);
+ assert(pure_runtime_restart(&source, &identity, port(&a), 8));
+
+ /* A completed consumer does not retain its input when the program has no
+ * input-backed reply. The producing domain can then be reclaimed early. */
+ PureProgram no_reply = identity;
+ no_reply.reply_input = false;
+ assert(pure_runtime_restart(&right, &no_reply, port(&c), 8));
+ original = submit(&source, "again", "last", 4);
+ assert(completed(&source, original).status == PURE_OK);
+ assert(pure_runtime_forward(original, &right, "no_reply", 0, &y) == PURE_OK);
+ assert(pure_runtime_release(original));
+ assert(completed(&right, y).body.size == 0 && a.live == 0);
+ assert(source.active == 0 && right.active == 1 && right.retained == 0);
+ assert(pure_runtime_release(y));
+}
+
+static void long_chain(void) {
+ enum { COUNT = 1024 };
+ PureWork *work = calloc(COUNT, sizeof(*work));
+ assert(work);
+ Host host = {0};
+ PureRuntime r;
+ assert(pure_runtime_init(&r, work, COUNT, &identity, port(&host), COUNT));
+ PureTicket ticket = submit(&r, "chain", "x", 1);
+ for (size_t i = 1; i < COUNT; ++i) {
+ assert(completed(&r, ticket).status == PURE_OK);
+ PureTicket next;
+ assert(pure_runtime_forward(ticket, &r, "chain", 0, &next) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ ticket = next;
+ }
+ assert(completed(&r, ticket).status == PURE_OK);
+ assert(host.allocations == 1 && r.active == COUNT);
+ assert(pure_runtime_release(ticket));
+ assert(r.retained == 0 && r.active == 0 && host.frees == 1);
+ free(work);
+}
+
+static void actual_storage(void) {
+ char directory[] = "/tmp/pure-runtime-check-XXXXXX";
+ assert(mkdtemp(directory));
+ char source_path[128], target_path[128], name[160];
+ snprintf(source_path, sizeof(source_path), "%s/source", directory);
+ snprintf(target_path, sizeof(target_path), "%s/target", directory);
+ assert(pure_store_init(source_path) == PURE_OK && pure_store_init(target_path) == PURE_OK);
+ PureProgram selection;
+ char error[160];
+ assert(pure_program_load("examples/selection.pure", &selection, error, sizeof(error)));
+ PureRuntime source, target;
+ PureWork a[2], b[2];
+ assert(pure_runtime_init(&source, a, 2, &selection, pure_store_host(source_path), 128));
+ assert(pure_runtime_init(&target, b, 2, &identity, pure_store_host(target_path), 128));
+ const unsigned char bytes[] = {1,0,0,0, 3,0,0,0, 'a','b','c','d','e'};
+ PureTicket ticket = submit(&source, "excerpt", bytes, sizeof(bytes)), consumer;
+ PureOutcome result = completed(&source, ticket);
+ assert(result.status == PURE_OK && result.body.size == 3 && !memcmp(result.body.data, "bcd", 3));
+ assert(pure_runtime_forward(ticket, &target, "archive", 0, &consumer) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ assert(source.active == 1 && source.retained == sizeof(bytes));
+ assert(completed(&target, consumer).status == PURE_OK);
+ assert(pure_runtime_release(consumer) && source.active == 0);
+ PureStoredView stored = {0};
+ assert(pure_store_get(target_path, "archive", 128, &stored) == PURE_OK);
+ assert(stored.body.size == 3 && !memcmp(stored.body.data, "bcd", 3));
+ pure_store_release(&stored);
+
+ assert(pure_runtime_accept(&source, PURE_INPUT_READ, "excerpt", 0, 0, &ticket) == PURE_OK);
+ assert(completed(&source, ticket).status == PURE_OK);
+ assert(pure_runtime_forward(ticket, &target, "snapshot", 0, &consumer) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ int64_t revision;
+ assert(pure_store_put(source_path, "excerpt", 1, (PureSpan){(const unsigned char *)"new", 3}, &revision) == PURE_OK);
+ result = completed(&target, consumer);
+ assert(result.body.size == 3 && !memcmp(result.body.data, "bcd", 3));
+ assert(pure_runtime_release(consumer));
+
+ unsigned char invalid[] = {255,255,255,255, 1,0,0,0, 'x'};
+ ticket = submit(&source, "invalid", invalid, sizeof(invalid));
+ assert(completed(&source, ticket).status == PURE_LIMIT);
+ assert(pure_runtime_release(ticket));
+ assert(pure_store_get(source_path, "invalid", 128, &stored) == PURE_NOT_FOUND);
+ assert(source.active == 0 && target.active == 0 && source.retained == 0 && target.retained == 0);
+ const char *files[] = {"source/obj-excerpt", "source/.writer.lock", "target/obj-archive",
+ "target/obj-snapshot", "target/.writer.lock"};
+ for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); ++i) {
+ snprintf(name, sizeof(name), "%s/%s", directory, files[i]);
+ assert(unlink(name) == 0);
+ }
+ assert(rmdir(source_path) == 0 && rmdir(target_path) == 0 && rmdir(directory) == 0);
+}
+
+int main(void) {
+ admission_and_lifecycle();
+ forwarding();
+ long_chain();
+ actual_storage();
+ printf("{\"runtime_tests\":\"passed\",\"domain_bytes\":%zu,\"work_slot_bytes\":%zu,"
+ "\"ticket_bytes\":%zu,\"prepared_program_bytes\":%zu,\"forwarding_chain\":1024,"
+ "\"native_storage_pipeline\":true}\n", sizeof(PureRuntime), sizeof(PureWork),
+ sizeof(PureTicket), sizeof(PureProgram));
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-splice.c b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-splice.c
new file mode 100644
index 0000000..5b8232b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/connections/test-splice.c
@@ -0,0 +1,172 @@
+#define _POSIX_C_SOURCE 200809L
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CHECK(x) do { if (!(x)) { fprintf(stderr, "line %d: %s\n", __LINE__, #x); exit(1); } } while (0)
+static int failed_stage = -1;
+int pure_store_test_fault(PureStoreStage stage) { return (int)stage == failed_stage; }
+
+static void expect(const char *path, const char *key, int64_t revision, PureSpan bytes) {
+ PureStoredView view;
+ CHECK(pure_store_get(path, key, PURE_OBJECT_LIMIT, &view) == PURE_OK);
+ CHECK(view.revision == revision && view.body.size == bytes.size);
+ CHECK(!bytes.size || !memcmp(view.body.data, bytes.data, bytes.size));
+ pure_store_release(&view);
+}
+
+static void parser(void) {
+ const char *get = "on get { let o = store.read(request.key); reply(o, o.body); }";
+ const char *layout = "layout E { marker: bytes[1]; remove: u32le; start: u32le; insert: bytes; }";
+ char source[2048], error[160];
+ PureProgram p;
+ snprintf(source, sizeof(source), "%s %s on put { let e = view(E, request.body); "
+ "let s = store.splice(request.key, request.revision, e.start, e.remove, e.insert); reply(s, e.insert); }", layout, get);
+ CHECK(pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(p.splice && p.input_required == 9 && p.splice_offset.value == 5 && p.splice_remove.value == 1);
+ unsigned char input[] = {0, 2,0,0,0, 3,0,0,0, 0,255};
+ PureSpan write, reply;
+ size_t offset, remove;
+ for (size_t n = 0; n < 9; ++n)
+ CHECK(!pure_program_input(&p, (PureSpan){input, n}, &write, &reply));
+ CHECK(pure_program_input(&p, (PureSpan){input, sizeof(input)}, &write, &reply));
+ CHECK(write.size == 2 && write.data == input + 9 && reply.data == write.data);
+ CHECK(pure_program_splice(&p, (PureSpan){input, sizeof(input)}, &offset, &remove));
+ CHECK(offset == 3 && remove == 2);
+
+ snprintf(source, sizeof(source), "%s on put { let s = store.splice(request.key, request.revision, 0, 0, request.body); reply(s); }", get);
+ CHECK(pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(pure_program_splice(&p, (PureSpan){0}, &offset, &remove) && offset == 0 && remove == 0);
+ const char *invalid[] = {
+ "let s = store.splice(request.key, request.revision, e.insert, 0, e.insert); reply(s);",
+ "let s = store.splice(request.key, request.revision, 0, 1449985, e.insert); reply(s);",
+ "let s = store.splice(request.key, request.revision, 0, 0, e.start); reply(s);",
+ "let s = store.splice(request.key, request.revision, 0, 0, e.insert); let t = store.write(request.key, request.revision, e.insert); reply(t);"
+ };
+ for (size_t i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i) {
+ snprintf(source, sizeof(source), "%s %s on put { let e = view(E, request.body); %s }", layout, get, invalid[i]);
+ unsigned char before[sizeof(p)];
+ memcpy(before, &p, sizeof(p));
+ CHECK(!pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(*error && !memcmp(before, &p, sizeof(p)));
+ }
+}
+
+static void storage(const char *path) {
+ /* Reference whole-value assembly exists only in this test oracle. */
+ unsigned char oracle[65536], before[65536], insert[9000];
+ for (size_t i = 0; i < sizeof(insert); ++i) insert[i] = (unsigned char)(i * 19u);
+ size_t length = 49157;
+ for (size_t i = 0; i < length; ++i) oracle[i] = (unsigned char)((i * 17u) ^ (i >> 8));
+ int64_t revision;
+ CHECK(pure_store_splice(path, "work", 0, 0, 0, (PureSpan){oracle, length}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ /* Prefix/suffix copies cross both scratch and mapping page boundaries. */
+ const size_t edits[][3] = {{16381, 7, 9000}, {0, 0, 5}, {50000, 1, 0}, {4095, 4097, 3}, {0, 0, 0}};
+ for (size_t i = 0; i < sizeof(edits) / sizeof(*edits); ++i) {
+ size_t offset = edits[i][0], remove = edits[i][1], count = edits[i][2], previous = length;
+ memcpy(before, oracle, length);
+ PureStoredView old;
+ CHECK(pure_store_get(path, "work", PURE_OBJECT_LIMIT, &old) == PURE_OK);
+ int64_t expected = revision;
+ CHECK(pure_store_splice(path, "work", expected, offset, remove, (PureSpan){insert, count}, &revision) == PURE_OK);
+ CHECK(revision == expected + 1);
+ memmove(oracle + offset + count, oracle + offset + remove, length - offset - remove);
+ memcpy(oracle + offset, insert, count);
+ length = length - remove + count;
+ expect(path, "work", revision, (PureSpan){oracle, length});
+ CHECK(old.body.size == previous && !memcmp(old.body.data, before, previous));
+ pure_store_release(&old);
+ }
+ int64_t latest = revision;
+ CHECK(pure_store_splice(path, "work", latest - 1, 0, 0, (PureSpan){insert, 1}, &revision) == PURE_CONFLICT);
+ CHECK(revision == latest);
+ CHECK(pure_store_splice(path, "work", latest, SIZE_MAX, 0, (PureSpan){0}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_splice(path, "work", latest, 0, SIZE_MAX, (PureSpan){0}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_splice(path, "work", latest, length + 1, 0, (PureSpan){0}, &revision) == PURE_LIMIT);
+ /* Rejected before reading the intentionally undersized insertion pointer. */
+ CHECK(pure_store_splice(path, "work", latest, 0, 0, (PureSpan){insert, PURE_OBJECT_LIMIT}, &revision) == PURE_LIMIT);
+ expect(path, "work", latest, (PureSpan){oracle, length});
+ CHECK(pure_store_splice(path, "missing", 0, 1, 0, (PureSpan){0}, &revision) == PURE_LIMIT);
+ PureStoredView view;
+ CHECK(pure_store_get(path, "missing", 0, &view) == PURE_NOT_FOUND);
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_splice(path, "work", latest, 1, 3, (PureSpan){insert, 5}, &revision) == PURE_STORE_ERROR);
+ expect(path, "work", latest, (PureSpan){oracle, length});
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_splice(path, "work", latest, length, 0, (PureSpan){insert, 5}, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == latest + 1);
+ failed_stage = -1;
+ memcpy(oracle + length, insert, 5); length += 5;
+ expect(path, "work", revision, (PureSpan){oracle, length});
+ CHECK(pure_store_splice(path, "work", revision, 0, length, (PureSpan){0}, &revision) == PURE_OK);
+ expect(path, "work", revision, (PureSpan){0});
+ char file[256];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(fd >= 0 && pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_splice(path, "work", INT64_MAX, 0, 0, (PureSpan){0}, &revision) == PURE_LIMIT);
+}
+
+static void runtime(const char *path) {
+ PureProgram program;
+ char error[160];
+ CHECK(pure_program_load("examples/editor.pure", &program, error, sizeof(error)));
+ PureRuntime runtime;
+ PureWork slots[1];
+ PureHost denied = pure_store_host(path);
+ denied.splice = NULL; /* ordinary writes do not grant permission to splice */
+ CHECK(pure_runtime_init(&runtime, slots, 1, &program, denied, 32));
+ PureTicket ticket = {0};
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "native", 0, 9, &ticket) == PURE_DENIED);
+ CHECK(!ticket.runtime && runtime.active == 0 && runtime.retained == 0);
+ CHECK(pure_runtime_restart(&runtime, &program, pure_store_host(path), 32));
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "native", 0, 9, &ticket) == PURE_OK);
+ CHECK(pure_runtime_cancel(ticket) && pure_runtime_release(ticket));
+ CHECK(!pure_runtime_step(&runtime));
+ PureStoredView view;
+ CHECK(pure_store_get(path, "native", 32, &view) == PURE_NOT_FOUND);
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "native", 0, 7, &ticket) == PURE_OK);
+ memset(pure_runtime_ingress(ticket, NULL), 0, 7);
+ CHECK(pure_runtime_ready(ticket) && pure_runtime_step(&runtime));
+ PureOutcome result;
+ CHECK(pure_runtime_result(ticket, &result) && result.status == PURE_LIMIT);
+ CHECK(pure_runtime_release(ticket) && runtime.commits == 0);
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "native", 0, 9, &ticket) == PURE_OK);
+ unsigned char *input = pure_runtime_ingress(ticket, NULL);
+ memset(input, 0, 8); input[8] = 'x';
+ CHECK(pure_runtime_ready(ticket) && pure_runtime_step(&runtime));
+ CHECK(pure_runtime_result(ticket, &result) && result.status == PURE_OK && result.revision == 1);
+ CHECK(result.body.size == 1 && result.body.data == input + 8 && runtime.retained == 9);
+ expect(path, "native", 1, (PureSpan){(const unsigned char *)"x", 1});
+ CHECK(pure_runtime_release(ticket) && runtime.retained == 0 && runtime.active == 0);
+}
+
+int main(void) {
+ parser();
+ char path[] = "/tmp/pure-splice-check-XXXXXX";
+ CHECK(mkdtemp(path) && pure_store_init(path) == PURE_OK);
+ storage(path);
+ runtime(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(strncmp(entry->d_name, ".pending-", 9));
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ puts("{\"splice_tests\":\"passed\",\"checks\":[\"authored-fields-and-atomic-parse-failure\","
+ "\"binary-edit-oracle-and-old-snapshot\",\"bounds-conflict-size-overflow\","
+ "\"publication-failures-and-uncertain-durability\",\"cancel-admission-and-borrowed-reply\"]}");
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/cli.mjs b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/cli.mjs
new file mode 100644
index 0000000..b67f4d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/cli.mjs
@@ -0,0 +1,127 @@
+#!/usr/bin/env node
+import { readFile, writeFile } from 'node:fs/promises';
+import { createInterface } from 'node:readline';
+import { createRuntime } from './web/runtime.mjs';
+import { parseProject } from './web/project.mjs';
+import { remoteTarget, pushProject, pullProject } from './remote.mjs';
+
+const help = `Pure authoring workbench · 같은 정의와 Zig 실행기
+ load PATH .pure 파일을 적용 (같은 이름의 상태 보존)
+ down NAME 정의한 입력 누르기
+ up NAME 정의한 입력 놓기
+ point NAME PHASE X Y 좌표 입력 (down / move / up / cancel)
+ point-target NAME VIEW PHASE X Y 그룹의 대상에 좌표 입력
+ change NAME VALUE 숫자 입력 전달
+ frame [1..600] 시간 진행, 1프레임 = 1/60초
+ show 상태와 도형 출력
+ limits C H W 표시 캐시(0..32)·변경 기록(0..8)·작업량(0..4294967295) 설정
+ forget [PART] 표시 기록 삭제: all, values, history (상태는 유지)
+ costs 마지막 표시 계산의 작업량·명령 수·캐시 적중 출력
+ reset 현재 정의의 초기 상태로
+ save PATH 적용한 정의를 저장
+ save-project PATH 적용 코드와 현재 배치를 JSON으로 저장
+ restore PATH 저장한 배치를 복원 (초안이 있으면 파일에 보존)
+ connect URL KEY 로컬 네이티브 저장 서버의 작업물에 연결
+ push [REVISION] 현재 배치를 저장 (첫 생성은 push 0, 충돌 시 기존 값 유지)
+ pull 원격 배치를 검증·복원하고 revision 기억
+ help / quit
+브라우저와 별도 인스턴스입니다. 임의 JavaScript는 실행하지 않습니다.`;
+
+async function main() {
+ const args = process.argv.slice(2);
+ if (args.includes('--help')) { console.log(help); return; }
+ if (args.length > 1) throw new Error('사용법: node cli.mjs [project.pure]');
+ const runtime = await createRuntime(await readFile(new URL('./web/core.wasm', import.meta.url)));
+ let savedDraft = null;
+ let remote = null, remoteRevision = null;
+ async function loadFile(path, restoreOnly = false) {
+ const content = await readFile(path, 'utf8');
+ if (restoreOnly || path.toLowerCase().endsWith('.json')) {
+ const project = parseProject(content);
+ if (project.version === 2) {
+ savedDraft = runtime.restoreDocument(project).draft;
+ return;
+ }
+ if (restoreOnly) throw new Error('현재 배치가 포함된 version 2 파일이 필요합니다.');
+ runtime.apply(project.source);
+ } else runtime.apply(content);
+ savedDraft = null;
+ }
+ if (args[0]) await loadFile(args[0]); else runtime.apply('');
+ const terminal = createInterface({ input: process.stdin, output: process.stdout, terminal: Boolean(process.stdin.isTTY) });
+ if (process.stdin.isTTY) console.log(help);
+ terminal.setPrompt('pure> ');
+ if (process.stdin.isTTY) terminal.prompt();
+ for await (const line of terminal) {
+ try {
+ const match = /^(\S+)(?:\s+(.+))?$/.exec(line.trim());
+ const name = match?.[1] || 'show';
+ const arg = match?.[2];
+ if (name === 'quit') { terminal.close(); break; }
+ if (name === 'help') console.log(help);
+ else if (name === 'costs' && !arg) console.log(JSON.stringify({ evaluation: runtime.evaluationStats() }));
+ else {
+ if (name === 'load' && arg) await loadFile(arg);
+ else if (name === 'restore' && arg) await loadFile(arg, true);
+ else if (name === 'connect' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('connect URL KEY 형식을 사용하세요.');
+ remote = remoteTarget(parts[0], parts[1]);
+ remoteRevision = null;
+ console.log(JSON.stringify({ remote: remote.href }));
+ } else if (name === 'push') {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const expected = arg ?? remoteRevision;
+ if (expected === null) throw new Error('먼저 pull로 버전을 읽거나 push 0으로 새 작업물을 만드세요.');
+ remoteRevision = await pushProject(remote, expected, runtime.exportDocument(savedDraft ?? undefined));
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, stored: true }));
+ } else if (name === 'pull' && !arg) {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const loaded = await pullProject(remote);
+ savedDraft = runtime.restoreDocument(loaded.project).draft;
+ remoteRevision = loaded.revision;
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, restored: true }));
+ }
+ else if (name === 'save-project' && arg) await writeFile(arg, JSON.stringify(runtime.exportDocument(savedDraft ?? undefined), null, 2) + '\n', {flag:'wx'});
+ else if (name === 'save' && arg) await writeFile(arg, runtime.exportProject().source, { flag: 'wx' });
+ else if (name === 'down' && arg) runtime.down(arg, 'terminal');
+ else if (name === 'up' && arg) runtime.up(arg, 'terminal');
+ else if (name === 'point' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 4) throw new Error('point NAME PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[1], Number(parts[2]), Number(parts[3]), 'terminal');
+ } else if (name === 'point-target' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 5) throw new Error('point-target NAME VIEW PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[2], Number(parts[3]), Number(parts[4]), 'terminal', parts[1]);
+ } else if (name === 'change' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('change NAME VALUE 형식을 사용하세요.');
+ runtime.change(parts[0], Number(parts[1]), 'terminal');
+ } else if (name === 'frame') {
+ if (arg !== undefined && !/^\d+$/.test(arg)) throw new Error('frame 1..600 정수를 입력하세요.');
+ const count = arg === undefined ? 1 : Number(arg);
+ if (count < 1 || count > 600) throw new Error('frame 1..600 정수를 입력하세요.');
+ runtime.frame(count);
+ } else if (name === 'reset' && !arg) runtime.reset();
+ else if (name === 'limits' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 3 || parts.some(part => !/^\d+$/.test(part)))
+ throw new Error('limits C H W 정수 세 개를 입력하세요.');
+ const [cacheEntries, historyEntries, workLimit] = parts.map(Number);
+ runtime.configureEvaluation({ cacheEntries, historyEntries, workLimit });
+ } else if (name === 'forget') runtime.forgetEvaluation(arg || 'all');
+ else if (name !== 'show' || arg) throw new Error('명령 형식을 확인하세요. help로 안내를 볼 수 있습니다.');
+ const result = runtime.snapshot();
+ console.log(JSON.stringify(result));
+ if (result.lastError && !process.stdin.isTTY) process.exitCode = 1;
+ }
+ } catch (error) {
+ console.error(`${error.line ? `${error.line}:${error.column || 1} ` : ''}${error.message}`);
+ if (!process.stdin.isTTY) process.exitCode = 1;
+ }
+ if (process.stdin.isTTY) terminal.prompt();
+ }
+}
+
+main().catch((error) => { console.error(error.message); process.exitCode = 1; });
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/examples/direct.pure b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/examples/direct.pure
new file mode 100644
index 0000000..b29721c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/examples/direct.pure
@@ -0,0 +1,47 @@
+# 도형을 잡은 위치를 유지해 이동합니다. 취소하면 잡기 전 위치로 돌아갑니다.
+state x = 80
+state y = 160
+state grab_x = 0
+state grab_y = 0
+state start_x = 80
+state start_y = 160
+state dragging = 0
+
+input drag = pointer(tile)
+input left = ArrowLeft
+input right = ArrowRight
+
+box left_area(20, 100, 280, 220, "#233a31")
+box right_area(340, 100, 280, 220, "#343b25")
+box tile(x, y, 56, 44, "#c9f08b")
+text horizontal(30, 45, x, "x: ")
+text vertical(180, 45, y, "y: ")
+text region(350, 70, x >= 320, "오른쪽 영역: ")
+text active(30, 75, dragging, "잡고 있음: ")
+
+on drag.down {
+ start_x = x
+ start_y = y
+ grab_x = event_x - x
+ grab_y = event_y - y
+ dragging = 1
+}
+on drag.move {
+ x = clamp(event_x - grab_x, 20, 564)
+ y = clamp(event_y - grab_y, 100, 276)
+}
+on drag.up {
+ # 놓기는 마지막으로 표시한 위치를 확정합니다.
+ dragging = 0
+}
+on drag.cancel {
+ x = start_x
+ y = start_y
+ dragging = 0
+}
+on left.down {
+ if dragging == 0 { x = max(20, x - 10) }
+}
+on right.down {
+ if dragging == 0 { x = min(564, x + 10) }
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/remote.mjs b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/remote.mjs
new file mode 100644
index 0000000..6ee6a59
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/remote.mjs
@@ -0,0 +1,89 @@
+import http from 'node:http';
+import { MAX_PROJECT_BYTES, parseProject } from './web/project.mjs';
+
+const maxRevision = 9223372036854775807n;
+function revisionText(value, allowZero = false) {
+ if (typeof value !== 'string' || !/^(0|[1-9]\d*)$/.test(value) ||
+ value.length > 19 || BigInt(value) > maxRevision || (!allowZero && value === '0'))
+ throw new Error('revision은 범위 안의 정수 문자열이어야 합니다.');
+ return value;
+}
+
+export function remoteTarget(base, key) {
+ const url = new URL(base);
+ if (url.protocol !== 'http:' || !['127.0.0.1', 'localhost'].includes(url.hostname) ||
+ url.username || url.password || url.pathname !== '/' || url.search || url.hash)
+ throw new Error('현재 연결 호스트는 로컬 http://127.0.0.1:PORT 형식을 사용합니다.');
+ if (!/^[A-Za-z0-9_-]{1,64}$/.test(key)) throw new Error('작업물 이름은 영문·숫자·_·- 1~64자입니다.');
+ url.hostname = '127.0.0.1';
+ url.pathname = `/objects/${key}`;
+ return url;
+}
+
+function request(url, method, body, headers = {}) {
+ return new Promise((resolve, reject) => {
+ let done = false;
+ const finish = (error, value) => {
+ if (done) return;
+ done = true;
+ clearTimeout(deadline);
+ if (error) reject(error); else resolve(value);
+ };
+ const req = http.request(url, { method, agent: false, headers: { ...headers,
+ 'Content-Length': body?.byteLength ?? 0, Connection: 'close' } }, (res) => {
+ const chunks = [];
+ let size = 0;
+ res.on('data', (chunk) => {
+ size += chunk.length;
+ if (size > MAX_PROJECT_BYTES) {
+ const error = new Error('서버 작업물이 허용 크기를 넘었습니다.');
+ finish(error);
+ res.destroy(error);
+ req.destroy(error);
+ } else chunks.push(chunk);
+ });
+ res.on('error', (error) => finish(error));
+ res.on('aborted', () => finish(new Error('응답이 완료되기 전에 연결이 끊겼습니다.')));
+ res.on('end', () => {
+ if (res.statusCode !== 200) {
+ const error = new Error(`원격 작업 실패: ${res.statusCode} ${res.headers['x-pure-error'] ?? ''}`.trim());
+ error.status = res.statusCode;
+ error.etag = res.headers.etag;
+ finish(error);
+ return;
+ }
+ try {
+ const match = /^"([1-9]\d*)"$/.exec(res.headers.etag ?? '');
+ if (!match) throw new Error('서버의 revision 응답이 올바르지 않습니다.');
+ const revision = revisionText(match[1]);
+ finish(null, { revision, bytes: Buffer.concat(chunks, size) });
+ } catch (error) { finish(error); }
+ });
+ });
+ const deadline = setTimeout(() => {
+ const error = new Error('원격 작업 시간 초과: 저장 완료 여부는 다시 확인해야 합니다.');
+ finish(error);
+ req.destroy(error);
+ }, 12000);
+ req.on('error', (error) => finish(error));
+ req.end(body);
+ });
+}
+
+export async function pushProject(target, expected, project) {
+ revisionText(expected, true);
+ const text = JSON.stringify(project);
+ parseProject(text);
+ const body = Buffer.from(text, 'utf8');
+ const headers = expected === '0' ? { 'If-None-Match': '*' } : { 'If-Match': `"${expected}"` };
+ const result = await request(target, 'PUT', body, headers);
+ return result.revision;
+}
+
+export async function pullProject(target) {
+ const result = await request(target, 'GET');
+ const text = new TextDecoder('utf-8', { fatal: true }).decode(result.bytes);
+ const project = parseProject(text);
+ if (project.version !== 2) throw new Error('현재 배치를 포함한 version 2 작업물이 필요합니다.');
+ return { project, revision: result.revision };
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/compiler.mjs b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/compiler.mjs
new file mode 100644
index 0000000..6aec335
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/compiler.mjs
@@ -0,0 +1,496 @@
+// Pure's experimental scalar interaction language. No host code is evaluated.
+const LIMITS = Object.freeze({ sourceBytes: 32768, states: 32, inputs: 8,
+ views: 24, handlers: 64, instructions: 512, depth: 64, stack: 64 });
+const RESERVED = new Set(['frame', 'dt', 'event_x', 'event_y', 'event_value', 'min', 'max', 'clamp']);
+const BINARY = new Map([
+ ['||', [1, 15]], ['&&', [2, 14]], ['==', [3, 12]], ['!=', [3, 13]],
+ ['<', [4, 8]], ['<=', [4, 9]], ['>', [4, 10]], ['>=', [4, 11]],
+ ['+', [5, 3]], ['-', [5, 4]], ['*', [6, 5]], ['/', [6, 6]],
+]);
+const FUNCTIONS = { min: [2, 17], max: [2, 18], clamp: [3, 19] };
+const VIEW_FIELDS = { box: ['x', 'y', 'width', 'height'],
+ circle: ['x', 'y', 'radius'], text: ['x', 'y', 'value'] };
+
+function fail(token, message) {
+ const error = new Error(`${message} (${token.line}:${token.column})`);
+ error.line = token.line;
+ error.column = token.column;
+ throw error;
+}
+
+function lex(source) {
+ const tokens = [];
+ let offset = 0, line = 1, column = 1;
+ const advance = () => {
+ const char = source[offset++];
+ if (char === '\n') { line++; column = 1; } else column++;
+ return char;
+ };
+ while (offset < source.length) {
+ const char = source[offset];
+ if (char === ' ' || char === '\t' || char === '\r') { advance(); continue; }
+ if (char === '#') { while (offset < source.length && source[offset] !== '\n') advance(); continue; }
+ const token = { line, column };
+ if (char === '\n') { advance(); tokens.push({ ...token, kind: 'nl' }); continue; }
+ if (char === '"') {
+ advance();
+ let value = '', closed = false;
+ while (offset < source.length) {
+ const next = advance();
+ if (next === '"') { closed = true; break; }
+ if (next === '\n' || next === '\r') fail(token, 'Strings must fit on one line');
+ if (next === '\\') {
+ const escaped = advance();
+ const escapes = { n: '\n', r: '\r', t: '\t', '"': '"', '\\': '\\' };
+ if (!Object.hasOwn(escapes, escaped)) fail(token, 'Unsupported string escape');
+ value += escapes[escaped];
+ } else value += next;
+ }
+ if (!closed) fail(token, 'Unterminated string');
+ tokens.push({ ...token, kind: 'string', value }); continue;
+ }
+ const remaining = source.slice(offset);
+ const number = remaining.match(/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/);
+ if (number) {
+ const value = Number(number[0]);
+ if (!Number.isFinite(value)) fail(token, 'Number must be finite');
+ for (let i = 0; i < number[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'number', value }); continue;
+ }
+ const name = remaining.match(/^[A-Za-z_][A-Za-z_0-9]*/);
+ if (name) {
+ for (let i = 0; i < name[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'name', value: name[0] }); continue;
+ }
+ const pair = source.slice(offset, offset + 2);
+ if (['<=', '>=', '==', '!=', '&&', '||'].includes(pair)) {
+ advance(); advance(); tokens.push({ ...token, kind: pair }); continue;
+ }
+ if ('=+-*/!<>(){},.;:'.includes(char)) {
+ advance(); tokens.push({ ...token, kind: char }); continue;
+ }
+ fail(token, `Unexpected character ${JSON.stringify(char)}`);
+ }
+ tokens.push({ kind: 'eof', line, column });
+ return tokens;
+}
+
+class Parser {
+ constructor(tokens) { this.tokens = tokens; this.position = 0; this.depth = 0; }
+ peek() { return this.tokens[this.position]; }
+ take() { return this.tokens[this.position++]; }
+ is(kind, value) { return this.peek().kind === kind && (value === undefined || this.peek().value === value); }
+ expect(kind, description = kind) {
+ if (!this.is(kind)) fail(this.peek(), `Expected ${description}`);
+ return this.take();
+ }
+ newlines() { while (this.is('nl')) this.take(); }
+ separators() { while (this.is('nl') || this.is(';')) this.take(); }
+ end() {
+ if (!['nl', ';', '}', 'eof'].includes(this.peek().kind)) fail(this.peek(), 'Expected newline or semicolon');
+ this.separators();
+ }
+ reference(token) {
+ if (!this.is('.')) return token.value;
+ this.take();
+ return `${token.value}.${this.expect('name', 'field name').value}`;
+ }
+ initial() {
+ let sign = 1;
+ if (this.is('-') || this.is('+')) sign = this.take().kind === '-' ? -1 : 1;
+ return sign * this.expect('number', 'numeric state initializer').value;
+ }
+ node(token, properties, children = []) {
+ const depth = 1 + Math.max(0, ...children.map(child => child.depth));
+ if (depth > LIMITS.depth) fail(token, 'Expression nesting exceeds 64');
+ return { token, depth, ...properties };
+ }
+ expression(minimum = 0, multiline = false) {
+ if (++this.depth > LIMITS.depth) fail(this.peek(), 'Expression nesting exceeds 64');
+ if (multiline) this.newlines();
+ const token = this.take();
+ let left;
+ if (token.kind === 'number') left = this.node(token, { kind: 'constant', value: token.value });
+ else if (token.kind === '-' || token.kind === '!') {
+ const child = this.expression(7, multiline);
+ left = this.node(token, { kind: 'unary', op: token.kind === '-' ? 7 : 16, child }, [child]);
+ } else if (token.kind === '(') {
+ left = this.expression(0, true); this.newlines(); this.expect(')');
+ } else if (token.kind === 'name') {
+ if (Object.hasOwn(FUNCTIONS, token.value) && this.is('(')) {
+ this.take();
+ const args = [];
+ this.newlines();
+ if (!this.is(')')) {
+ for (;;) {
+ args.push(this.expression(0, true)); this.newlines();
+ if (!this.is(',')) break;
+ this.take();
+ }
+ }
+ this.expect(')');
+ if (args.length !== FUNCTIONS[token.value][0]) fail(token, `${token.value} expects ${FUNCTIONS[token.value][0]} arguments`);
+ left = this.node(token, { kind: 'call', op: FUNCTIONS[token.value][1], args }, args);
+ } else left = this.node(token, { kind: 'reference', name: this.reference(token) });
+ } else fail(token, 'Expected a number, state, or expression');
+ for (;;) {
+ if (multiline) this.newlines();
+ const entry = BINARY.get(this.peek().kind);
+ if (!entry || entry[0] < minimum) break;
+ const operator = this.take();
+ const right = this.expression(entry[0] + 1, multiline);
+ left = this.node(operator, { kind: 'binary', op: entry[1], left, right }, [left, right]);
+ }
+ this.depth--;
+ return left;
+ }
+ block(depth = 0) {
+ if (depth >= LIMITS.depth) fail(this.peek(), 'Handler nesting exceeds 64');
+ this.newlines(); this.expect('{'); this.separators();
+ const statements = [];
+ while (!this.is('}')) {
+ const token = this.expect('name', 'assignment, if, or closing brace');
+ if (token.value === 'if' && !this.is('=')) {
+ const condition = this.expression();
+ const body = this.block(depth + 1);
+ statements.push({ kind: 'if', token, condition, body });
+ } else {
+ const name = this.reference(token);
+ this.expect('=');
+ statements.push({ kind: 'assign', token, name, expression: this.expression() });
+ }
+ this.end();
+ }
+ this.take();
+ return statements;
+ }
+ parse() {
+ const declarations = [];
+ this.separators();
+ while (!this.is('eof')) {
+ const token = this.expect('name', 'declaration');
+ const kind = token.value;
+ if (kind === 'state') {
+ const name = this.expect('name', 'state name'); this.expect('=');
+ declarations.push({ kind, token, name, initial: this.initial() });
+ } else if (kind === 'record') {
+ const name = this.expect('name', 'record type'); this.newlines(); this.expect('{'); this.separators();
+ const fields = [];
+ while (!this.is('}')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,fields});
+ } else if (kind === 'item') {
+ const name = this.expect('name', 'item name'); this.expect('=');
+ const type = this.expect('name', 'record type'); this.expect('('); this.newlines();
+ const fields = [];
+ while (!this.is(')')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.newlines();
+ if (!this.is(',')) break;
+ this.take(); this.newlines();
+ }
+ this.expect(')'); declarations.push({kind,token,name,type,fields});
+ } else if (kind === 'rule') {
+ const name = this.expect('name', 'rule name'); this.expect('(');
+ const parameter = this.expect('name', 'record parameter'); this.expect(':');
+ const type = this.expect('name', 'record type'); this.expect(')');
+ declarations.push({kind,token,name,parameter,type,body:this.block()});
+ } else if (kind === 'input') {
+ const name = this.expect('name', 'input name'); this.expect('=');
+ const key = this.expect('name', 'keyboard code or pointer(view)');
+ if (key.value === 'value') {
+ declarations.push({kind,token,name,valueInput:true}); this.end(); continue;
+ }
+ if (key.value === 'pointer') {
+ if (this.is('{')) {
+ this.take(); this.separators(); const routes = [];
+ while (!this.is('}')) {
+ const target = this.expect('name', 'view ID'); this.expect(':');
+ const item = this.expect('name', 'item name'); routes.push({target,item}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,routes}); this.end(); continue;
+ }
+ this.expect('(');
+ const target = this.expect('name', 'view ID'); this.expect(')');
+ declarations.push({ kind, token, name, target });
+ this.end(); continue;
+ }
+ if (!/^(?:Space|Enter|Arrow(?:Left|Right|Up|Down)|Key[A-Z]|Digit[0-9])$/.test(key.value)) fail(key, 'Unsupported keyboard code');
+ declarations.push({ kind, token, name, key });
+ } else if (Object.hasOwn(VIEW_FIELDS, kind)) {
+ const name = this.expect('name', 'view ID'); this.expect('(');
+ const expressions = [];
+ for (let i = 0; i < VIEW_FIELDS[kind].length; i++) {
+ if (i) { this.newlines(); this.expect(','); }
+ expressions.push(this.expression(0, true));
+ }
+ this.newlines();
+ let color, prefix = '';
+ if (kind !== 'text') {
+ this.expect(','); this.newlines();
+ const value = this.expect('string', 'literal hex color');
+ if (!/^#[0-9a-fA-F]{6}$/.test(value.value)) fail(value, 'Color must use six hexadecimal digits, such as "#356548"');
+ color = value.value;
+ } else if (this.is(',')) { this.take(); this.newlines(); prefix = this.expect('string', 'literal text prefix').value; }
+ this.newlines(); this.expect(')');
+ declarations.push({ kind: 'view', type: kind, token, name, expressions, color, prefix });
+ } else if (kind === 'on') {
+ const event = this.expect('name', 'input name or frame');
+ let edge;
+ if (event.value !== 'frame') {
+ this.expect('.'); edge = this.expect('name', 'down, up, move or cancel');
+ if (!['down', 'up', 'move', 'cancel', 'change'].includes(edge.value)) fail(edge, 'Expected down or up, move, cancel or change');
+ }
+ if (this.is('name', 'use')) {
+ this.take(); const rule = this.expect('name', 'rule name'); this.expect('(');
+ const item = this.expect('name', 'item name or input.target');
+ const argument = this.reference(item); this.expect(')');
+ declarations.push({kind:'handler',token,event,edge,rule,item,argument});
+ } else declarations.push({ kind: 'handler', token, event, edge, body: this.block() });
+ } else fail(token, `Unknown declaration ${kind}`);
+ this.end();
+ }
+ return declarations;
+ }
+}
+
+export function compile(source) {
+ if (typeof source !== 'string') fail({ line: 1, column: 1 }, 'Source must be a string');
+ const sourceBytes = new TextEncoder().encode(source).length;
+ if (sourceBytes > LIMITS.sourceBytes) fail({ line: 1, column: 1 }, 'Source exceeds 32768 UTF-8 bytes');
+ const declarations = new Parser(lex(source)).parse();
+ const program = { states: [], inputs: [], instructions: [], handlers: [], views: [], pointerTargets: [], metrics: {} };
+ const states = new Map(), inputs = new Map(), views = new Set(), keys = new Set(), targets = new Set();
+ const records = new Map(), items = new Map(), rules = new Map();
+ const scalarNames = new Set(declarations.filter(d => d.kind === 'state').map(d => d.name.value));
+ for (const declaration of declarations) {
+ if (!['record','rule'].includes(declaration.kind)) continue;
+ const {name,fields,kind} = declaration, symbols = kind === 'record' ? records : rules;
+ if (RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (kind === 'record') {
+ if (!fields.length || fields.length > 8) fail(name, 'A record needs 1..8 fields');
+ const used = new Set();
+ for (const field of fields) {
+ if (used.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ if (RESERVED.has(field.name.value)) fail(field.name, `Reserved name ${field.name.value}`);
+ used.add(field.name.value);
+ }
+ }
+ symbols.set(name.value, declaration);
+ }
+ let handlerCount = 0;
+ for (const declaration of declarations) {
+ const { kind, name, token } = declaration;
+ if (name && RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (kind === 'record' || kind === 'rule') continue;
+ if (kind === 'item') {
+ if (items.has(name.value) || scalarNames.has(name.value)) fail(name, `Duplicate state/item ${name.value}`);
+ const record = records.get(declaration.type.value);
+ if (!record) fail(declaration.type, `Unknown record ${declaration.type.value}`);
+ const overrides = new Map();
+ for (const field of declaration.fields) {
+ if (!record.fields.some(f => f.name.value === field.name.value)) fail(field.name, `Unknown field ${field.name.value}`);
+ if (overrides.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ overrides.set(field.name.value, field.initial);
+ }
+ const base = states.size;
+ for (const field of record.fields) {
+ if (states.size >= LIMITS.states) fail(name, 'At most 32 states are allowed, including item fields');
+ const qualified = `${name.value}.${field.name.value}`, index = states.size;
+ states.set(qualified,index);
+ program.states.push({name:qualified,initial:overrides.has(field.name.value) ? overrides.get(field.name.value) : field.initial,line:token.line});
+ }
+ items.set(name.value,{type:declaration.type.value,base,count:record.fields.length});
+ } else if (kind === 'state' || kind === 'input') {
+ const symbols = kind === 'state' ? states : inputs;
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (symbols.size >= LIMITS[`${kind}s`]) fail(name, `At most ${LIMITS[`${kind}s`]} ${kind}s are allowed`);
+ symbols.set(name.value, symbols.size);
+ if (kind === 'state') program.states.push({ name: name.value, initial: declaration.initial, line: token.line });
+ else if (declaration.valueInput) {
+ program.inputs.push({name:name.value,kind:'value',line:token.line});
+ } else if (declaration.routes) {
+ if (!declaration.routes.length) fail(name, 'A pointer group needs at least one target');
+ program.inputs.push({name:name.value, routes:[], line:token.line});
+ } else if (declaration.target) {
+ const target = declaration.target;
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ targets.add(target.value);
+ program.inputs.push({ name: name.value, target: target.value, line: token.line });
+ } else {
+ if (keys.has(declaration.key.value)) fail(declaration.key, `Duplicate keyboard code ${declaration.key.value}`);
+ keys.add(declaration.key.value);
+ program.inputs.push({ name: name.value, key: declaration.key.value, line: token.line });
+ }
+ } else if (kind === 'view') {
+ if (views.has(name.value)) fail(name, `Duplicate view ID ${name.value}`);
+ if (views.size >= LIMITS.views) fail(name, 'At most 24 views are allowed');
+ views.add(name.value);
+ } else if (++handlerCount > LIMITS.handlers) fail(token, 'At most 64 handlers are allowed');
+ }
+ for (const declaration of declarations) {
+ if (declaration.target && !views.has(declaration.target.value))
+ fail(declaration.target, `Unknown pointer target ${declaration.target.value}`);
+ }
+ const routedItems = new Set();
+ for (const declaration of declarations) {
+ if (!declaration.routes) continue;
+ const input = inputs.get(declaration.name.value), resolved = program.inputs[input];
+ let type;
+ for (const {target,item:token} of declaration.routes) {
+ if (!views.has(target.value)) fail(target, `Unknown pointer target ${target.value}`);
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ const item = items.get(token.value);
+ if (!item) fail(token, `Unknown item ${token.value}`);
+ if (type && type !== item.type) fail(token, 'Pointer group targets must share one record type');
+ if (routedItems.has(token.value)) fail(token, `Item ${token.value} already has a pointer route`);
+ targets.add(target.value); routedItems.add(token.value); type = item.type;
+ const route = program.pointerTargets.length;
+ if (route >= 24) fail(target, 'At most 24 pointer targets are allowed');
+ program.pointerTargets.push({input,base:item.base,count:item.count});
+ resolved.routes.push({target:target.value, item:token.value, route});
+ }
+ resolved.type = type;
+ }
+ for (const rule of rules.values()) {
+ if (!records.has(rule.type.value)) fail(rule.type, `Unknown record ${rule.type.value}`);
+ if (RESERVED.has(rule.parameter.value)) fail(rule.parameter, `Reserved name ${rule.parameter.value}`);
+ }
+ let pointHandler = false, valueHandler = false;
+ let parameters = null;
+ let parameterPrefix = null;
+ let stack = 0, maxStack = 0;
+ const emit = (op, token, arg = 0, value = 0, delta = 0) => {
+ if (program.instructions.length >= LIMITS.instructions) fail(token, 'At most 512 instructions are allowed');
+ stack += delta;
+ if (stack < 0 || stack > LIMITS.stack) fail(token, 'Expression stack exceeds 64');
+ maxStack = Math.max(maxStack, stack);
+ program.instructions.push({ op, arg, value, line: token.line });
+ };
+ const expression = (node, binding = false) => {
+ const { token } = node;
+ if (node.kind === 'constant') emit(0, token, 0, node.value, 1);
+ else if (node.kind === 'reference') {
+ if (node.name === 'event_value') {
+ if (binding || !valueHandler) fail(token, 'event_value is only available in value change handlers');
+ emit(26, token, 0, 0, 1);
+ } else if (node.name === 'event_x' || node.name === 'event_y') {
+ if (binding || !pointHandler) fail(token, 'event_x and event_y are only available in pointer handlers');
+ emit(node.name === 'event_x' ? 22 : 23, token, 0, 0, 1);
+ } else if (node.name === 'dt') {
+ if (binding) fail(token, 'dt is only available in handlers');
+ emit(2, token, 0, 0, 1);
+ } else {
+ if (parameterPrefix && node.name.startsWith(parameterPrefix) && !parameters.has(node.name))
+ fail(token, `Unknown parameter field ${node.name}`);
+ if (parameters?.has(node.name)) {
+ emit(24, token, parameters.get(node.name), 0, 1);
+ return;
+ }
+ if (!states.has(node.name)) fail(token, `Unknown state ${node.name}`);
+ emit(1, token, states.get(node.name), 0, 1);
+ }
+ } else if (node.kind === 'unary') { expression(node.child, binding); emit(node.op, token); }
+ else if (node.kind === 'binary') {
+ expression(node.left, binding); expression(node.right, binding); emit(node.op, token, 0, 0, -1);
+ } else {
+ for (const arg of node.args) expression(arg, binding);
+ emit(node.op, token, 0, 0, 1 - node.args.length);
+ }
+ };
+ const statements = body => {
+ for (const statement of body) {
+ if (statement.kind === 'assign') {
+ if (parameterPrefix && statement.name.startsWith(parameterPrefix) && !parameters.has(statement.name))
+ fail(statement.token, `Unknown parameter field ${statement.name}`);
+ const parameter = parameters?.get(statement.name);
+ if (parameter === undefined && !states.has(statement.name)) fail(statement.token, `Unknown state ${statement.name}`);
+ expression(statement.expression);
+ emit(parameter === undefined ? 20 : 25, statement.token, parameter === undefined ? states.get(statement.name) : parameter, 0, -1);
+ } else {
+ expression(statement.condition);
+ const branch = program.instructions.length;
+ emit(21, statement.token, 0, 0, -1);
+ statements(statement.body);
+ program.instructions[branch].arg = program.instructions.length;
+ }
+ }
+ };
+ const bodies = new Map();
+ function ruleBody(rule) {
+ if (bodies.has(rule.name.value)) return bodies.get(rule.name.value);
+ parameterPrefix = `${rule.parameter.value}.`;
+ parameters = new Map(records.get(rule.type.value).fields.map((field,index) => [`${rule.parameter.value}.${field.name.value}`,index]));
+ // A shared body may read coordinates; every binding is checked below.
+ pointHandler = true; valueHandler = true; stack = 0;
+ const start = program.instructions.length;
+ statements(rule.body);
+ const length = program.instructions.length - start;
+ const point = program.instructions.slice(start).some(op => op.op === 22 || op.op === 23);
+ parameters = null; parameterPrefix = null;
+ const value = program.instructions.slice(start).some(op => op.op === 26);
+ const body = {start,length,point,value}; bodies.set(rule.name.value,body); return body;
+ }
+ for (const declaration of declarations) {
+ if (declaration.kind === 'handler') {
+ let event = 0;
+ pointHandler = false; valueHandler = false;
+ if (declaration.event.value !== 'frame') {
+ if (!inputs.has(declaration.event.value)) fail(declaration.event, `Unknown input ${declaration.event.value}`);
+ const index = inputs.get(declaration.event.value), edge = declaration.edge.value;
+ pointHandler = Boolean(program.inputs[index].target || program.inputs[index].routes);
+ valueHandler = program.inputs[index].kind === 'value';
+ if (valueHandler !== (edge === 'change')) fail(declaration.edge, 'Value inputs require change; change requires a value input');
+ if (!pointHandler && (edge === 'move' || edge === 'cancel')) fail(declaration.edge, 'move and cancel require a pointer input');
+ event = edge === 'change' ? 33 + index : edge === 'move' ? 17 + index : edge === 'cancel' ? 25 + index : 1 + index * 2 + (edge === 'up' ? 1 : 0);
+ }
+ if (declaration.rule) {
+ const rule = rules.get(declaration.rule.value);
+ const routed = declaration.argument.includes('.');
+ const input = program.inputs[inputs.get(declaration.event.value)];
+ if (routed && (!input?.routes || declaration.argument !== `${declaration.event.value}.target`))
+ fail(declaration.item, 'Use the current pointer group target');
+ const item = routed ? {type:input.type, count:records.get(input.type).fields.length} : items.get(declaration.item.value);
+ if (!rule) fail(declaration.rule, `Unknown rule ${declaration.rule.value}`);
+ if (!item) fail(declaration.item, `Unknown item ${declaration.item.value}`);
+ if (item.type !== rule.type.value) fail(declaration.item, `Rule ${rule.name.value} requires ${rule.type.value}`);
+ const pointer = pointHandler, value = valueHandler;
+ const body = ruleBody(rule);
+ if (body.value && !value) fail(declaration.rule, 'Value-reading rules require a value input');
+ if (body.point && !pointer) fail(declaration.rule, 'Coordinate-reading rules require a pointer input');
+ program.handlers.push({event,start:body.start,length:body.length,line:declaration.token.line,parameterBase:routed ? 255 : item.base,parameterCount:item.count});
+ } else {
+ const start = program.instructions.length;
+ stack = 0; statements(declaration.body);
+ program.handlers.push({ event, start, length: program.instructions.length - start, line: declaration.token.line });
+ }
+ } else if (declaration.kind === 'view') {
+ const view = { id: declaration.name.value, type: declaration.type, line: declaration.token.line, bindings: {} };
+ if (view.type === 'text') view.prefix = declaration.prefix;
+ else view.color = declaration.color;
+ declaration.expressions.forEach((node, index) => {
+ const start = program.instructions.length;
+ stack = 0; expression(node, true);
+ view.bindings[VIEW_FIELDS[view.type][index]] = { start, length: program.instructions.length - start };
+ });
+ program.views.push(view);
+ }
+ }
+ // Unused definitions still receive name/type checking, but reserve no VM body.
+ for (const rule of rules.values()) {
+ if (bodies.has(rule.name.value)) continue;
+ const instructions = program.instructions, previousMax = maxStack;
+ program.instructions = [];
+ ruleBody(rule);
+ program.instructions = instructions; maxStack = previousMax;
+ }
+ program.metrics = { sourceBytes, sourceLines: source === '' ? 0 : source.split('\n').length,
+ states: states.size, inputs: inputs.size, views: views.size,
+ handlers: program.handlers.length, instructions: program.instructions.length, maxStack };
+ return program;
+}
+
+export { LIMITS };
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/core.wasm b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/core.wasm
new file mode 100644
index 0000000..79c50a8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/core.wasm
Binary files differ
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/project.mjs b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/project.mjs
new file mode 100644
index 0000000..861e0fc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/project.mjs
@@ -0,0 +1,47 @@
+import { compile } from './compiler.mjs';
+
+// Two escaped source strings plus up to 32 generated item.field names. A long
+// schema field can appear in every item without repeating in the source text.
+export const MAX_PROJECT_BYTES = (2 * 6 + 32) * 32768 + 8192;
+const encoder = new TextEncoder();
+function sourceText(value, label) {
+ if (typeof value !== 'string' || encoder.encode(value).length > 32768)
+ throw new Error(`${label}: UTF-8 32 KiB 이하의 코드가 필요합니다.`);
+ return value;
+}
+
+// No runtime mutation. Validate every saved value before opening core staging.
+export function validateDocument(document) {
+ if (!document || typeof document !== 'object' || Array.isArray(document) ||
+ document.format !== 'pure-workbench' || document.version !== 2)
+ throw new Error('배치 파일 형식이 맞지 않습니다. pure-workbench version 2가 필요합니다.');
+ const source = sourceText(document.source, '적용된 코드');
+ const draft = sourceText(Object.hasOwn(document, 'draft') ? document.draft : source, '편집 중인 코드');
+ const program = compile(source);
+ if (!Array.isArray(document.states) || document.states.length !== program.states.length)
+ throw new Error('저장된 상태 목록이 적용된 코드와 일치하지 않습니다.');
+ const values = new Map();
+ for (const entry of document.states) {
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry) || typeof entry.name !== 'string' || values.has(entry.name))
+ throw new Error('상태 이름이 잘못됐거나 중복됐습니다.');
+ const value = entry.value === '-0' ? -0 : entry.value;
+ if (typeof value !== 'number' || !Number.isFinite(value)) throw new Error('상태 값은 유한한 숫자여야 합니다.');
+ values.set(entry.name, value);
+ }
+ for (const state of program.states)
+ if (!values.has(state.name)) throw new Error(`저장된 상태가 없습니다: ${state.name}`);
+ return { source, draft, program, values: program.states.map(state => values.get(state.name)) };
+}
+
+export function parseProject(text) {
+ if (typeof text !== 'string' || encoder.encode(text).length > MAX_PROJECT_BYTES)
+ throw new Error('작업 파일이 너무 큽니다.');
+ let project;
+ try { project = JSON.parse(text); } catch { throw new Error('올바른 JSON 파일이 아닙니다.'); }
+ if (!project || typeof project !== 'object' || Array.isArray(project) || project.format !== 'pure-workbench')
+ throw new Error('Pure 작업물 형식이 아닙니다.');
+ if (project.version === 1) sourceText(project.source, '코드');
+ else if (project.version === 2) validateDocument(project);
+ else throw new Error('지원하지 않는 작업 파일 버전입니다.');
+ return project;
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/runtime.mjs b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/runtime.mjs
new file mode 100644
index 0000000..d8d6618
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/sources/prototypes/workbench/web/runtime.mjs
@@ -0,0 +1,350 @@
+import { compile } from './compiler.mjs';
+import { validateDocument } from './project.mjs';
+
+const messages = [
+ '', '실행기의 용량 한도를 넘었습니다.', '실행 정의가 유효하지 않습니다.',
+ '계산 스택의 범위를 벗어났습니다.', '0으로 나눌 수 없습니다.',
+ '계산 결과가 유한한 수의 범위를 벗어났습니다.', '조건 분기 범위가 유효하지 않습니다.',
+ '존재하지 않는 상태를 참조했습니다.', '시간 간격이 유효하지 않습니다.',
+ '정의되지 않은 입력 사건입니다.',
+];
+const sourceLimit = 32768;
+
+function problem(message, line = null, column = null) {
+ return Object.assign(new Error(message), { line, column });
+}
+
+function freezeProgram(value) {
+ if (value && typeof value === 'object') {
+ for (const child of Object.values(value)) freezeProgram(child);
+ Object.freeze(value);
+ }
+ return value;
+}
+
+export async function createRuntime(wasmBytes, evaluationOptions = {}) {
+ if (wasmBytes === undefined) {
+ const response = await fetch(new URL('./core.wasm', import.meta.url), { cache: 'no-store' });
+ if (!response.ok) throw new Error(`실행기를 불러오지 못했습니다 (HTTP ${response.status}).`);
+ wasmBytes = await response.arrayBuffer();
+ }
+ const module = await WebAssembly.compile(wasmBytes);
+ if (WebAssembly.Module.imports(module).length) throw new Error('이 실행기는 호스트 함수 없이 동작해야 합니다.');
+ const { exports: core } = await WebAssembly.instantiate(module, {});
+ if (typeof core.eval_bounded !== 'function' || typeof core.abort_program !== 'function' || typeof core.dispatch_point !== 'function' || typeof core.put_restored_value !== 'function' || typeof core.commit_restored_program !== 'function' || typeof core.bind_handler !== 'function' || typeof core.put_pointer_target !== 'function' || typeof core.bind_target_handler !== 'function' || typeof core.dispatch_target !== 'function' || typeof core.dispatch_value !== 'function')
+ throw new Error('실행기 버전이 맞지 않습니다. 새로고침하거나 core.wasm을 다시 빌드하세요.');
+ core.reset_all();
+ let program = null;
+ let appliedSource = '';
+ let lastEvent = null;
+ // Keep a failed event visible through its release/focus-loss cleanup.
+ // The active program can clear this diagnostic by apply or explicit reset.
+ let lastFailure = null;
+ const held = new Map();
+ const points = new Map();
+ let presenting = false;
+ let bindings = [];
+ let pointRoutes = new Map();
+ // One bounded publication buffer, never exposed to callers. No state mirror.
+ let displayValues = null, displayValid = null;
+ function available() {
+ if (presenting) throw new Error('출력 전달 중에는 실행기를 다시 호출할 수 없습니다.');
+ }
+ let evaluationPolicy = { cacheEntries: 0, historyEntries: 8, workLimit: 2048 };
+
+ function checked(code, line = null) {
+ if (code !== 0) throw problem(messages[code] || `실행기 오류 ${code}`, line);
+ }
+ function inputIndex(name) {
+ const index = program?.inputs.findIndex((input) => input.name === name) ?? -1;
+ if (index < 0) throw new Error(`정의되지 않은 입력: ${name}`);
+ return index;
+ }
+ function dispatch(event, name, phase, source, point = null, value = undefined) {
+ const status = value !== undefined ? core.dispatch_value(event, value) : point ? (point.route === undefined ? core.dispatch_point(event, point.x, point.y)
+ : core.dispatch_target(event, point.route, point.x, point.y)) : core.dispatch(event, event === 0 ? 1 / 60 : 0);
+ const pc = core.info(2) >>> 0;
+ lastEvent = { name, phase, source, status,
+ line: program?.instructions[pc]?.line ?? null, ops: core.info(3) >>> 0 };
+ if (point) { lastEvent.x = point.x; lastEvent.y = point.y; if (point.target) lastEvent.target = point.target; }
+ if (value !== undefined) lastEvent.value = value;
+ if (status) lastFailure = { ...lastEvent };
+ return status;
+ }
+
+ function evaluateDisplay() {
+ core.begin_evaluation(evaluationPolicy.workLimit);
+ if (!bindings.length) return null;
+ displayValues ??= new Float64Array(96);
+ displayValid ??= new Uint8Array(24);
+ let error = null, slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ displayValid[i] = 1;
+ for (const [name, binding] of bindings[i]) {
+ const value = core.eval_bounded(binding.start, binding.length);
+ if (core.evaluation_info(0) === 10) {
+ displayValid.fill(0);
+ return { code: 101, line: view.line,
+ message: '표시 계산의 작업량 한도를 넘었습니다. 한도를 늘리거나 표시식을 줄이세요.' };
+ }
+ if (!Number.isFinite(value) || ((name === 'width' || name === 'height' || name === 'radius') && value < 0)) {
+ error ??= { line: view.line, message: `${view.id}.${name}: 표시할 수 없는 값입니다. 0 나눗셈이나 음수 크기를 확인하세요.` };
+ displayValid[i] = 0;
+ }
+ displayValues[slot++] = value;
+ }
+ }
+ return error;
+ }
+
+ function status(viewError) {
+ const executionError = lastFailure?.status || 0;
+ return {
+ tick: core.info(0) >>> 0, revision: core.info(4) >>> 0,
+ displayError: viewError ? { code: viewError.code || 100, ...viewError } : null,
+ lastError: executionError || (viewError ? viewError.code || 100 : 0),
+ errorMessage: executionError ? messages[executionError] || `실행 오류 ${executionError}` : viewError?.message || '',
+ errorLine: executionError ? lastFailure.line : viewError?.line ?? null,
+ lastOps: core.info(3) >>> 0, successfulEvents: core.info(9) >>> 0,
+ held: [...held.keys()], lastEvent: lastEvent ? { ...lastEvent } : null,
+ lastFailure: lastFailure ? { ...lastFailure } : null,
+ memory: {
+ linearBytes: core.memory.buffer.byteLength,
+ reservedEngineBytes: core.layout(0), programReservedBytes: core.layout(1),
+ instructionBytes: core.layout(2), handlerBytes: core.layout(3),
+ activeIRBytes: core.layout(4), activeStateBytes: core.layout(5),
+ stagingReservedBytes: core.layout(6), evalStackBytes: core.layout(7),
+ pointerTargetBytes: core.layout(8), pointerTargets: core.layout(9),
+ },
+ };
+ }
+
+ function load(next, source, restored = null) {
+ const oldIds = new Map(restored ? [] : program?.states.map((state, index) => [state.name, index]) ?? []);
+ checked(core.begin_program(next.states.length, next.inputs.length));
+ try {
+ for (let index = 0; index < next.states.length; index++) {
+ const state = next.states[index];
+ checked(core.put_state(index, state.initial, oldIds.get(state.name) ?? -1), state.line);
+ if (restored) checked(core.put_restored_value(index, restored[index]), state.line);
+ }
+ for (const op of next.instructions) checked(core.put_instruction(op.op, op.arg, op.value), op.line);
+ for (const target of next.pointerTargets) checked(core.put_pointer_target(target.input, target.base, target.count));
+ for (const [index, handler] of next.handlers.entries()) {
+ checked(core.put_handler(handler.event, handler.start, handler.length), handler.line);
+ if (handler.parameterCount)
+ checked(handler.parameterBase === 255 ? core.bind_target_handler(index, handler.parameterCount)
+ : core.bind_handler(index, handler.parameterBase, handler.parameterCount), handler.line);
+ }
+ checked(restored ? core.commit_restored_program() : core.commit_program());
+ } catch (error) {
+ core.abort_program();
+ throw error;
+ }
+ pointRoutes = new Map(next.inputs.flatMap(input => (input.routes ?? []).map(route => [route.target, route])));
+ program = next;
+ bindings = next.views.map(view => Object.entries(view.bindings));
+ appliedSource = source;
+ lastEvent = null;
+ lastFailure = null;
+ }
+
+ const api = {
+ get currentProgram() { return program; },
+ configureEvaluation({ cacheEntries = evaluationPolicy.cacheEntries,
+ historyEntries = evaluationPolicy.historyEntries, workLimit = evaluationPolicy.workLimit } = {}) {
+ available();
+ for (const [name, value, maximum] of [['cacheEntries', cacheEntries, 32],
+ ['historyEntries', historyEntries, 8], ['workLimit', workLimit, 0xffffffff]]) {
+ if (!Number.isInteger(value) || value < 0 || value > maximum)
+ throw new Error(`${name}: 0~${maximum} 사이의 정수여야 합니다.`);
+ }
+ checked(core.configure_evaluation(cacheEntries, historyEntries));
+ evaluationPolicy = { cacheEntries, historyEntries, workLimit };
+ return { ...evaluationPolicy };
+ },
+ forgetEvaluation(part = 'all') {
+ available();
+ const flags = part === 'all' ? 3 : part === 'values' ? 1 : part === 'history' ? 2 : undefined;
+ if (flags === undefined) throw new Error('삭제할 기록은 values, history, all 중 하나여야 합니다.');
+ core.forget_evaluation(flags);
+ },
+ evaluationStats() {
+ return { ...evaluationPolicy, work: core.evaluation_info(1),
+ instructions: core.evaluation_info(2), cacheHits: core.evaluation_info(3),
+ reservedBytes: core.evaluation_info(6), dedicatedBytes: core.evaluation_info(7),
+ sharedBytes: core.evaluation_info(8), reuseAvailable: Boolean(core.evaluation_info(9)),
+ workspaceTagBytes: core.evaluation_info(10) };
+ },
+ apply(source) {
+ available();
+ if (typeof source !== 'string' || new TextEncoder().encode(source).length > sourceLimit) {
+ throw problem('정의는 UTF-8 기준 32,768바이트 이하의 텍스트여야 합니다.');
+ }
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 적용하세요. 현재 작업은 그대로 유지합니다.');
+ const next = freezeProgram(compile(source));
+ load(next, source);
+ return next;
+ },
+ restoreDocument(document) {
+ available();
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 복원하세요.');
+ const next = validateDocument(document);
+ load(freezeProgram(next.program), next.source, next.values);
+ return { source: next.source, draft: next.draft };
+ },
+ exportDocument(draft = appliedSource) {
+ available();
+ if (!program) throw problem('먼저 코드를 적용하세요.');
+ if (held.size) throw problem('조작을 끝낸 뒤 배치를 저장하세요.');
+ if (lastFailure) throw problem('실행 오류를 해결한 뒤 배치를 저장하세요.');
+ if (typeof draft !== 'string' || new TextEncoder().encode(draft).length > sourceLimit)
+ throw problem('편집 중인 코드는 UTF-8 32 KiB 이하여야 합니다.');
+ return { format: 'pure-workbench', version: 2, source: appliedSource, draft,
+ states: program.states.map((state, i) => {
+ const value = core.get_state(i);
+ return { name: state.name, value: Object.is(value, -0) ? '-0' : value };
+ }) };
+ },
+ reset() {
+ available();
+ held.clear();
+ points.clear();
+ core.reset_state();
+ lastEvent = null;
+ lastFailure = null;
+ },
+ frame(count = 1) {
+ available();
+ if (!Number.isInteger(count) || count < 0 || count > 600) throw new Error('프레임 수는 0~600 사이의 정수여야 합니다.');
+ if (!program) return 0;
+ for (let i = 0; i < count; i++) {
+ const code = dispatch(0, 'frame', 'frame', 'clock');
+ if (code !== 0) return code;
+ }
+ return 0;
+ },
+ down(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name) || new Set();
+ if (sources.has(source)) return 0;
+ const wasDown = sources.size > 0;
+ sources.add(source);
+ held.set(name, sources);
+ return wasDown ? 0 : dispatch(1 + index * 2, name, 'down', source);
+ },
+ up(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name);
+ if (!sources?.delete(source)) return 0;
+ if (sources.size) return 0;
+ held.delete(name);
+ return dispatch(2 + index * 2, name, 'up', source);
+ },
+ change(name, value, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind !== 'value') throw new Error('숫자 값에 연결된 입력이 아닙니다.');
+ if (!Number.isFinite(value)) throw new Error('입력 값은 유한한 숫자여야 합니다.');
+ return dispatch(33 + index, name, 'change', source, null, value);
+ },
+ point(name, phase, x, y, source = 'external', target = undefined) {
+ available();
+ const index = inputIndex(name);
+ const input = program.inputs[index];
+ if (!input.target && !input.routes) throw new Error('포인터에 연결된 입력이 아닙니다.');
+ const route = input.routes ? pointRoutes.get(target) : undefined;
+ if (input.routes && (!route || program.pointerTargets[route.route].input !== index)) throw new Error('포인터 그룹에 연결된 도형 이름이 필요합니다.');
+ if (!input.routes && target !== undefined) throw new Error('단일 포인터 입력에는 대상 인자를 지정하지 않습니다.');
+ const owner = route ? `${name}:${target}` : name;
+ if (!['down', 'move', 'up', 'cancel'].includes(phase)) throw new Error('포인터 단계는 down, move, up, cancel 중 하나여야 합니다.');
+ if (!Number.isFinite(x) || !Number.isFinite(y)) throw new Error('포인터 좌표는 유한한 숫자여야 합니다.');
+ if (typeof source !== 'string' || source.length === 0) throw new Error('포인터 출처 이름이 필요합니다.');
+ let point = points.get(owner);
+ if (phase === 'down') {
+ if (point?.source === source) return 0;
+ if (point) throw new Error('이 입력은 다른 포인터가 사용 중입니다.');
+ point = {name, source, x, y, target, route:route?.route};
+ points.set(owner, point);
+ held.set(owner, new Set([source]));
+ } else {
+ if (!point || point.source !== source) return 0;
+ point.x = x; point.y = y;
+ if (phase === 'up' || phase === 'cancel') { points.delete(owner); held.delete(owner); }
+ }
+ const event = phase === 'move' ? 17 + index : phase === 'cancel' ? 25 + index : 1 + index * 2 + (phase === 'up' ? 1 : 0);
+ return dispatch(event, name, phase, source, point);
+ },
+ releaseAll() {
+ available();
+ let firstError = 0;
+ for (const point of [...points.values()]) {
+ const status = api.point(point.name, 'cancel', point.x, point.y, point.source, point.target);
+ if (!firstError) firstError = status;
+ }
+ for (const [name, sources] of [...held]) {
+ for (const source of [...sources]) {
+ const status = api.up(name, source);
+ if (!firstError) firstError = status;
+ }
+ }
+ return firstError;
+ },
+ exportProject() {
+ return { format: 'pure-workbench', version: 1, source: appliedSource };
+ },
+ // Synchronous trusted output adapter. Callbacks run only after the whole
+ // display has been evaluated. Runtime mutation/reentrant reads are refused.
+ // Exceptions from an adapter propagate; the next call republishes all values.
+ present(target) {
+ available();
+ presenting = true;
+ try {
+ const { begin, state, view, value, end } = target;
+ for (const callback of [begin, state, view, value, end])
+ if (typeof callback !== 'function') throw new TypeError('출력 어댑터 함수가 필요합니다.');
+ const error = evaluateDisplay();
+ begin.call(target, program);
+ for (let i = 0; i < (program?.states.length ?? 0); i++) state.call(target, i, core.get_state(i));
+ let slot = 0, visible = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const valid = Boolean(displayValid[i]);
+ view.call(target, i, valid);
+ for (const [name] of bindings[i]) {
+ if (valid) value.call(target, i, name, displayValues[slot]);
+ slot++;
+ }
+ if (valid) visible++;
+ }
+ end.call(target, visible);
+ return status(error);
+ } finally { presenting = false; }
+ },
+ snapshot() {
+ available();
+ const error = evaluateDisplay();
+ const states = Object.fromEntries((program?.states ?? []).map((state, index) => [state.name, core.get_state(index)]));
+ const views = [];
+ let slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ const rendered = displayValid[i] ? { id: view.id, type: view.type, color: view.color, prefix: view.prefix } : null;
+ for (const [name] of bindings[i]) {
+ if (rendered) rendered[name] = displayValues[slot];
+ slot++;
+ }
+ if (rendered) views.push(rendered);
+ }
+ return { states, views, ...status(error) };
+ },
+ };
+ api.configureEvaluation(evaluationOptions);
+ return Object.freeze(api);
+}
diff --git a/prototypes/connections/results/2026-09-23-document-edits/verification.json b/prototypes/connections/results/2026-09-23-document-edits/verification.json
new file mode 100644
index 0000000..598aed9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-document-edits/verification.json
@@ -0,0 +1,32 @@
+{
+ "sources_verified_and_frozen": 37,
+ "native_and_sanitized_source_hashes_match": true,
+ "recorded_binaries_verified": 8,
+ "integration_scenarios_per_build": 36,
+ "server_runs_per_build": 19,
+ "all_server_runs_drained": true,
+ "compiler": "cc (Debian 14.2.0-19) 14.2.0",
+ "core_sections": {
+ "text": 5932,
+ "data": 0,
+ "bss": 0
+ },
+ "structure_sizes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "core_external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "server_structure_bytes": [41528],
+ "limitations": [
+ "synchronous full-file rewrite with 4096-byte host scratch",
+ "11-byte credit test does not measure total memory",
+ "limited storage authoring profile, no native GUI or secure peer RPC",
+ "GNU footprint tooling validated on Linux AArch64; macOS unverified"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/README.md b/prototypes/connections/results/2026-09-23-execution-core/README.md
new file mode 100644
index 0000000..fd92adb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/README.md
@@ -0,0 +1,28 @@
+# 실행 코어 검증 기록
+
+2026-09-23, Linux AArch64, GCC 14.2.0. 첫 공개 체크포인트 진행 중의 증거다.
+
+- `native.json`: 일반 빌드의 실제 TCP 28개 시나리오, 실행 코어의 수명·예산·세대·내부 전달·실제 저장 검사.
+- `sanitized.json`: 같은 경로를 ASan·UBSan 및 기본 누수 검사로 통과한 결과.
+- `verification.json`: 두 결과의 소스 일치, 바이너리 해시, 종료 시 자원 회수, 코어 외부 심볼과 크기 기록.
+- `sources/`: 결과에 기록된 30개 소스·클라이언트 파일의 해시 검증 후 복사본.
+
+당시 실행 명령은 `prototypes/connections`에서 다음과 같다.
+
+```sh
+make all
+make check EVIDENCE=results/2026-09-23-execution-core/native.json
+make check BUILD=build/sanitized CFLAGS='-std=c17 -O1 -g -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer' EVIDENCE=results/2026-09-23-execution-core/sanitized.json
+size build/runtime.o build/evaluate.o build/pure-connections
+nm -u build/libpure-execution.a
+```
+
+기존 증거 파일은 덮어쓰지 않는다. 재현할 때는 `EVIDENCE`를 생략하거나 새 경로를 사용한다.
+동결된 소스는 `sources/prototypes/connections`에서 `make all`과 `make check`로 빌드·검사할 수 있다.
+검사에는 C17 컴파일러·make·Python·Node와 로컬 소켓/자식 프로세스 실행이 필요하다.
+
+영역 192 B, 작업 슬롯 224 B, 티켓 24 B는 구조체 크기다. 코어 오브젝트의 `size text` 합
+5,672 B는 전체 RSS가 아니다. 준비 프로그램·작업 슬롯·실제 본문·호스트 자원 등은 별도이며,
+서버 구조체는 기능 추가로 이전보다 1,664 B 증가했다. 처리량·지연의 우위를 측정한 자료가 아니다.
+동기 효과·단일 소유 스레드·get/put 작성 프로필이라는 현재 한계는
+[022 보고서](../../../../docs/research/022-execution-core.md)에 기록했다.
diff --git a/prototypes/connections/results/2026-09-23-execution-core/native.json b/prototypes/connections/results/2026-09-23-execution-core/native.json
new file mode 100644
index 0000000..173e833
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/native.json
@@ -0,0 +1,505 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 648,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ]
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 648,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ]
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ }
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 31,
+ "ingress_prefix_copy_bytes": 11679,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 8,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41488
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 192,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 648,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "f0700e597f634c2304ccb4cbc375d8b491964ed8be6e2aa573a58df9ee00c5fe",
+ "binary_sha256": "09ecc629b9bbddf09f5b6090c9b67eec7d2e70c6065624c60b902b5b3f8ae802",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "b7e7d6806cf9785df1d01f2418d1e493eaf2d4b9cf43abc90082c60bd61dcd0b",
+ "prototypes/connections/store.h": "d2d7f8bd9845ce13095520f4401b9c48b1b4e8b6da10f8c4c63ab495c2950ef5",
+ "prototypes/connections/program.c": "b72b0aef7fc04ef044e3c0d177222aea688765526316fe2d0de988573ce8003b",
+ "prototypes/connections/program.h": "2c3c955967883a9a8ea4566a006eccd44f3a173ac0682c2f272d09700f209639",
+ "prototypes/connections/runtime.c": "d1163fdc6e5a1948ec0109fc1d04312a0b71edebf8f3762f38ac674ccd686af3",
+ "prototypes/connections/runtime.h": "03a69db466a217fff195183af174acba1949772c16523aab6f425e84600798e5",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "d3fbbd4ddba2b7fe29fc11ba46d3fc471945f724afff52bb5d7699f79cb80b5d",
+ "prototypes/connections/store-port.c": "5c7c3c1dcd2ae90a39ecc93b5bccf7f54fcafe1d0e10b2ad7b1eb0c89c1382bf",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "d1e2dc14185a8b4301cc6bfa001ee2cdfa674acad505b92c51f06311abf36be9",
+ "prototypes/connections/server.c": "21dc7edf1acb58f347586a92bab02f2d7edf6a7369c9b8212acab8b87f58aa74",
+ "prototypes/connections/check.py": "6bf6ccb8acd14a01f635733d3a9a42439a6f9dc37a9d43b5e3681301a9ab2235",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "1c4083e549bf2bb83e0127c910607e60cefd6f3af9e1fae355caadb2506ded09",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sanitized.json b/prototypes/connections/results/2026-09-23-execution-core/sanitized.json
new file mode 100644
index 0000000..67c195e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sanitized.json
@@ -0,0 +1,505 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 648,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ]
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 648,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ]
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ }
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 31,
+ "ingress_prefix_copy_bytes": 14232,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41488
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41488
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 192,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 648,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "eb526e3dff8a87f1f53446efa25026a9720058bf414be08ce8cc57a9787c6bb8",
+ "binary_sha256": "49fb5aec3b1ec71cea66ab708e507583cc2403203845e8737a8c0fb2a050a899",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "b7e7d6806cf9785df1d01f2418d1e493eaf2d4b9cf43abc90082c60bd61dcd0b",
+ "prototypes/connections/store.h": "d2d7f8bd9845ce13095520f4401b9c48b1b4e8b6da10f8c4c63ab495c2950ef5",
+ "prototypes/connections/program.c": "b72b0aef7fc04ef044e3c0d177222aea688765526316fe2d0de988573ce8003b",
+ "prototypes/connections/program.h": "2c3c955967883a9a8ea4566a006eccd44f3a173ac0682c2f272d09700f209639",
+ "prototypes/connections/runtime.c": "d1163fdc6e5a1948ec0109fc1d04312a0b71edebf8f3762f38ac674ccd686af3",
+ "prototypes/connections/runtime.h": "03a69db466a217fff195183af174acba1949772c16523aab6f425e84600798e5",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "d3fbbd4ddba2b7fe29fc11ba46d3fc471945f724afff52bb5d7699f79cb80b5d",
+ "prototypes/connections/store-port.c": "5c7c3c1dcd2ae90a39ecc93b5bccf7f54fcafe1d0e10b2ad7b1eb0c89c1382bf",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "d1e2dc14185a8b4301cc6bfa001ee2cdfa674acad505b92c51f06311abf36be9",
+ "prototypes/connections/server.c": "21dc7edf1acb58f347586a92bab02f2d7edf6a7369c9b8212acab8b87f58aa74",
+ "prototypes/connections/check.py": "6bf6ccb8acd14a01f635733d3a9a42439a6f9dc37a9d43b5e3681301a9ab2235",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "1c4083e549bf2bb83e0127c910607e60cefd6f3af9e1fae355caadb2506ded09",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/Makefile b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/Makefile
new file mode 100644
index 0000000..ea15285
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/Makefile
@@ -0,0 +1,43 @@
+CC ?= cc
+CFLAGS ?= -O2 -g
+CFLAGS += -std=c17 -Wall -Wextra -Wpedantic -Werror
+BUILD ?= build
+
+.PHONY: all check
+CORE = runtime.c evaluate.c
+HOST = store.c store-port.c
+HEADERS = runtime.h program.h store.h store-port.h flow.h result.h
+all: $(BUILD)/pure-connections $(BUILD)/libpure-execution.a
+
+$(BUILD):
+ mkdir -p $@
+
+$(BUILD)/pure-connections: server.c $(HOST) flow.c program.c $(CORE) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) server.c $(HOST) flow.c program.c $(CORE) $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/runtime.o: runtime.c $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c runtime.c -o $@
+
+$(BUILD)/evaluate.o: evaluate.c program.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c evaluate.c -o $@
+
+$(BUILD)/libpure-execution.a: $(BUILD)/runtime.o $(BUILD)/evaluate.o
+ $(AR) rcs $@ $^
+
+$(BUILD)/test-flow: test-flow.c store.c flow.c store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_STORE_TEST test-flow.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-program: test-program.c program.c evaluate.c program.h store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-program.c program.c evaluate.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-fields: test-fields.c program.c evaluate.c program.h store.h flow.h result.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-fields.c program.c evaluate.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-runtime: test-runtime.c program.c $(CORE) $(HOST) $(HEADERS) | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-runtime.c program.c $(CORE) $(HOST) $(LDFLAGS) $(LDLIBS) -o $@
+
+check: $(BUILD)/test-flow $(BUILD)/test-program $(BUILD)/test-fields $(BUILD)/test-runtime $(BUILD)/pure-connections
+ $(BUILD)/test-flow
+ $(BUILD)/test-program
+ $(BUILD)/test-fields
+ python3 check.py --server $(BUILD)/pure-connections --runtime-test $(BUILD)/test-runtime $(if $(EVIDENCE),--output "$(EVIDENCE)")
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/check.py b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/check.py
new file mode 100644
index 0000000..a512748
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/check.py
@@ -0,0 +1,536 @@
+#!/usr/bin/env python3
+"""Exercise local TCP, immutable byte extents, and the existing workbench CLI."""
+import argparse
+from contextlib import contextmanager
+from concurrent.futures import ThreadPoolExecutor
+import fcntl
+import hashlib
+import http.client
+import json
+import platform
+from pathlib import Path
+import select
+import socket
+import struct
+import subprocess
+import sys
+import tempfile
+import time
+
+ROOT = Path(__file__).resolve().parent
+WORKBENCH = ROOT.parent / 'workbench'
+OBJECT_LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+class Server:
+ def __init__(self, binary, storage, budget=4 * 1024 * 1024, timeout=5000, program=None):
+ self.process = subprocess.Popen([str(binary), '--store', str(storage), '--port', '0',
+ '--program', str(program or ROOT / 'examples/storage.pure'),
+ '--budget', str(budget), '--timeout-ms', str(timeout), '--send-buffer', '4096'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
+ if not select.select([self.process.stdout], [], [], 15)[0]:
+ self.process.kill()
+ raise AssertionError('server readiness timed out')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.ready = json.loads(line)
+ self.port = self.ready['port']
+ self.stats = None
+
+ def close(self):
+ if self.process.poll() is None:
+ self.process.terminate()
+ try:
+ stdout, stderr = self.process.communicate(timeout=10)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.process.communicate()
+ raise
+ assert self.process.returncode == 0, (stdout, stderr)
+ self.stats = json.loads(stderr)
+ assert self.stats['active'] == self.stats['retained_payload_bytes'] == 0
+ assert self.stats['peak_retained_payload_bytes'] <= self.stats['payload_budget']
+ assert self.stats['peak_connections'] <= 8
+
+
+@contextmanager
+def serving(*args, **kwargs):
+ server = Server(*args, **kwargs)
+ try:
+ yield server
+ finally:
+ server.close()
+
+
+def rpc(server, method, key, body=b'', expected=None):
+ headers = {'Content-Length': str(len(body))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = '*' if expected == 0 else f'"{expected}"'
+ connection = http.client.HTTPConnection('127.0.0.1', server.port, timeout=8)
+ try:
+ connection.request(method, f'/objects/{key}', body, headers)
+ response = connection.getresponse()
+ return response.status, dict(response.getheaders()), response.read()
+ finally:
+ connection.close()
+
+
+def wire(server, request, chunks=None):
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ if chunks:
+ for chunk in chunks:
+ sock.sendall(chunk)
+ else:
+ sock.sendall(request)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ return response.status, dict(response.getheaders()), response.read()
+
+
+def header(method, key, size=0, condition=b''):
+ return (f'{method} /objects/{key} HTTP/1.1\r\nHost: localhost\r\n'
+ f'Content-Length: {size}\r\n'.encode() + condition + b'\r\n')
+
+
+def cli(server, commands, source=None, expected_code=0):
+ result = subprocess.run(['node', str(WORKBENCH / 'cli.mjs'), *([str(source)] if source else [])],
+ input=commands.replace('$URL', f'http://127.0.0.1:{server.port}'), text=True,
+ capture_output=True, timeout=30)
+ assert result.returncode == expected_code, (result.stdout, result.stderr)
+ return [json.loads(line) for line in result.stdout.splitlines()], result.stderr
+
+
+def check(binary, directory):
+ storage = directory / 'objects'
+ checks, records = [], []
+ with serving(binary, storage) as server:
+ assert rpc(server, 'GET', 'absent')[0] == 404
+ payload = b'\x00\xffbinary\r\n\r\n' + bytes(range(256)) * 41
+ request = header('PUT', 'binary', len(payload), b'If-None-Match: *\r\n') + payload
+ status, headers, _ = wire(server, request, [request[:7], request[7:51], request[51:57], request[57:]])
+ assert status == 200 and headers['ETag'] == '"1"'
+ assert rpc(server, 'GET', 'binary')[2] == payload
+ checks.append('fragmented request and binary bytes round trip')
+ assert rpc(server, 'PUT', 'binary', b'new', 0)[0] == 412
+ assert rpc(server, 'PUT', 'binary', b'new', 1)[0] == 200
+ assert rpc(server, 'PUT', 'binary', b'stale', 1)[0] == 412
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('conditional create and stale revision preserve committed bytes')
+
+ with (storage / '.writer.lock').open('r+b') as lock:
+ fcntl.lockf(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ assert rpc(server, 'PUT', 'binary', b'blocked', 2)[0] == 503
+ fcntl.lockf(lock, fcntl.LOCK_UN)
+ broken = storage / 'obj-broken'
+ broken.write_bytes(b'incomplete')
+ assert rpc(server, 'GET', 'broken')[0] == 500
+ assert rpc(server, 'PUT', 'broken', b'failure', 0)[0] == 500
+ assert broken.read_bytes() == b'incomplete'
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('writer contention and invalid extent fail without overwriting data')
+
+ with serving(binary, storage) as second_writer:
+ with ThreadPoolExecutor(max_workers=2) as pool:
+ tasks = [pool.submit(rpc, target, 'PUT', 'race', value, 0)
+ for target, value in [(server, b'first'), (second_writer, b'second')]]
+ statuses = [task.result()[0] for task in tasks]
+ assert statuses.count(200) == 1 and all(status in [200, 412, 503] for status in statuses)
+ status, headers, body = rpc(server, 'GET', 'race')
+ assert status == 200 and headers['ETag'] == '"1"' and body in [b'first', b'second']
+ records.append(second_writer.stats)
+ checks.append('two native writers cannot both create the same expected revision')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'incomplete', 100, b'If-None-Match: *\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ sock.close()
+ assert rpc(server, 'GET', 'incomplete')[0] == 404
+ checks.append('incomplete request never commits and releases its allocation')
+
+ # Force genuine partial socket sends. A write on another connection must
+ # not alter the immutable file whose bytes are still being transmitted.
+ large = bytes(range(256)) * 4096
+ assert rpc(server, 'PUT', 'large', large, 0)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.getheader('ETag') == '"1"'
+ assert response.read(17) == large[:17]
+ assert rpc(server, 'PUT', 'large', b'changed', 1)[0] == 200
+ assert response.read() == large[17:]
+ sock.close()
+ assert rpc(server, 'GET', 'large')[2] == b'changed'
+ checks.append('borrowed read remains the same snapshot during another commit')
+
+ assert rpc(server, 'PUT', 'large', large, 2)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ assert sock.recv(1)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ sock.close()
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('receiver reset aborts an outstanding borrowed transfer')
+
+ assert wire(server, header('PUT', 'too_large', OBJECT_LIMIT + 1, b'If-None-Match: *\r\n'))[0] == 413
+ malformed = [
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nContent-Length: 1\r\nContent-Length: 1\r\nIf-None-Match: *\r\n\r\nx',
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n',
+ b'GET /objects/bad HTTP/1.1\r\nHost: x\x00hidden\r\n\r\n',
+ ]
+ for request in malformed:
+ assert wire(server, request)[0] == 400
+ assert rpc(server, 'GET', 'bad')[0] == 404
+ checks.append('unsupported framing and oversized payload are rejected before effects')
+
+ # Existing authoring path: define, manipulate, save remotely, reconstruct
+ # in a fresh runtime. No fabricated project fixture or mock storage.
+ source = WORKBENCH / 'examples' / 'direct.pure'
+ saved = directory / 'restored.json'
+ lines, _ = cli(server, 'point drag down 80 180\npoint drag move 210 210\npoint drag up 210 210\n'
+ 'connect $URL authored\npush 0\nquit\n', source)
+ snapshots = [line for line in lines if 'states' in line]
+ assert snapshots
+ expected_states = snapshots[-1]['states']
+ assert expected_states['x'] == 210 and expected_states['y'] == 190 and expected_states['dragging'] == 0
+ lines, _ = cli(server, f'connect $URL authored\npull\nsave-project {saved}\nquit\n')
+ assert [line for line in lines if 'states' in line][-1]['states'] == expected_states
+ document = json.loads(saved.read_text())
+ assert document['version'] == 2 and document['source'] == source.read_text()
+ lines, error = cli(server, 'connect $URL authored\npush 0\nquit\n', source, 1)
+ assert '412' in error
+ checks.append('existing workbench manipulation restores in a fresh runtime and reports conflict')
+
+ assert rpc(server, 'PUT', 'invalid_project', b'{"format":"pure-workbench","version":2,"source":"state x=1","states":[]}', 0)[0] == 200
+ lines, error = cli(server, 'show\nconnect $URL invalid_project\npull\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and error
+ lines, error = cli(server, 'point drag down 90 170\nconnect $URL authored\npull\npush\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and states[-1]['dragging'] == 1
+ assert len(error.strip().splitlines()) == 2
+ checks.append('invalid or non-idle restore preserves local state and does not adopt remote revision')
+
+ assert rpc(server, 'PUT', 'wide_revision', rpc_bytes(saved), 0)[0] == 200
+ wide = storage / 'obj-wide_revision'
+ raw = wide.read_bytes()
+ wide.write_bytes(raw[:8] + struct.pack('<Q', 9007199254740993) + raw[16:])
+ lines, _ = cli(server, 'connect $URL wide_revision\npull\npush\nquit\n')
+ revisions = [line['revision'] for line in lines if 'remote' in line and 'revision' in line]
+ assert revisions == ['9007199254740993', '9007199254740994']
+ checks.append('revision above JavaScript safe integer round trips without numeric coercion')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'unread_ack', 4, b'If-None-Match: *\r\n') + b'done')
+ try:
+ deadline = time.monotonic() + 3
+ while True:
+ committed = storage / 'obj-unread_ack'
+ if committed.exists():
+ assert committed.read_bytes()[24:] == b'done'
+ break
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ finally:
+ sock.close() # Client never consumes the successful response.
+ assert rpc(server, 'PUT', 'unread_ack', b'again', 0)[0] == 412
+ assert rpc(server, 'GET', 'unread_ack')[2] == b'done'
+ checks.append('unread acknowledgment does not undo commit or permit a stale retry')
+
+ # A disconnect after commit can hide the ACK; retries remain conditional.
+ assert rpc(server, 'PUT', 'empty', b'', 0)[0] == 200
+ assert rpc(server, 'GET', 'empty')[2] == b''
+ checks.append('empty body has a valid lifetime and stored revision')
+ records.append(server.stats)
+
+ with serving(binary, storage) as restarted:
+ assert rpc(restarted, 'GET', 'binary')[2] == b'new'
+ assert rpc(restarted, 'GET', 'authored')[2] == rpc_bytes(saved)
+ checks.append('committed authoring state survives process restart')
+ records.append(restarted.stats)
+
+ # Fixed small payload budget is an admission test, not a throughput workload.
+ with serving(binary, storage, budget=1024 * 1024, timeout=1200) as limited:
+ sock = socket.create_connection(('127.0.0.1', limited.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200
+ assert response.read(1) == large[:1]
+ status, headers, _ = rpc(limited, 'GET', 'large')
+ assert status == 503 and headers['X-Pure-Error'] == 'payload_budget'
+ # Leave the first receiver stalled until the absolute connection deadline.
+ time.sleep(1.4)
+ assert rpc(limited, 'GET', 'binary')[2] == b'new'
+ response.close()
+ sock.close()
+ checks.append('slow consumer retains its lease; budget rejects another; deadline releases it')
+
+ idle = [socket.create_connection(('127.0.0.1', limited.port), timeout=8) for _ in range(8)]
+ try:
+ for s in idle:
+ s.sendall(b'G')
+ for s in idle:
+ assert s.recv(1) == b''
+ finally:
+ for s in idle:
+ s.close()
+ assert rpc(limited, 'GET', 'binary')[0] == 200
+ checks.append('connection slots stay bounded and recover after header deadlines')
+ assert limited.stats['budget_rejections'] >= 1 and limited.stats['expired'] >= 9
+ records.append(limited.stats)
+ prepared = authored_connections(binary, directory, storage, records, checks)
+ fields = field_connections(binary, directory, storage, records, checks)
+ return {'kind': 'prepared-connection-correctness-not-performance', 'checks': checks,
+ 'prepared_connections': prepared,
+ 'field_connections': fields,
+ 'server_runs': records, 'storage': server.ready['storage']}
+
+
+def authored_connections(binary, directory, storage, records, checks):
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); }'
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); }'
+
+ def author(name, source):
+ path = directory / name
+ path.write_text(source)
+ return path
+
+ def explain(path):
+ return json.loads(subprocess.check_output([str(binary), '--check-program', str(path)], text=True))
+
+ with serving(binary, storage) as writer:
+ assert rpc(writer, 'PUT', 'short_parent', bytes(range(48)), 0)[0] == 200
+ assert rpc(writer, 'PUT', 'short_unused', bytes(range(80)), 0)[0] == 200
+ records.append(writer.stats)
+ excerpt = ROOT / 'examples/excerpt.pure'
+ prepared = {'excerpt': explain(excerpt)}
+ assert prepared['excerpt']['read'] == {
+ 'to_end': False, 'offset': 32, 'length': 16, 'minimum_source_bytes': 80}
+ with serving(binary, storage, budget=16, program=excerpt) as selected:
+ status, headers, body = rpc(selected, 'GET', 'large')
+ assert status == 200 and body == bytes(range(32, 48)) and headers['ETag'] == '"3"'
+ # Final [32,48) fits, but the authored parent [16,80) does not.
+ assert rpc(selected, 'GET', 'short_parent')[0] == 413
+ assert rpc(selected, 'GET', 'missing')[0] == 404
+ assert selected.stats['peak_retained_payload_bytes'] == 16
+ records.append(selected.stats)
+ checks.append('authored nested read maps only final demand while preserving parent bounds and revision')
+
+ unused = author('unused.pure', 'on get { let o = store.read(request.key); '
+ 'let unused = range(o.body, 0, 96); let body = range(o.body, 32, 16); reply(o, body); } ' + put)
+ with serving(binary, storage, budget=16, program=unused) as guarded:
+ assert rpc(guarded, 'GET', 'short_unused')[0] == 413
+ assert rpc(guarded, 'GET', 'large')[2] == bytes(range(32, 48))
+ records.append(guarded.stats)
+ checks.append('unused checked view still fails even when response range would be valid')
+
+ select_write = author('write.pure', get + ' on put { let a = range(request.body, 2, 10); '
+ 'let b = range(a, 3, 4); let alias = b; '
+ 'let saved = store.write(request.key, request.revision, alias); reply(saved, b); }')
+ prepared['write'] = explain(select_write)
+ with serving(binary, storage, program=select_write) as writer:
+ status, headers, body = rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'GET', 'selected')[2] == b'5678'
+ assert rpc(writer, 'PUT', 'selected', b'012345678', 1)[0] == 413
+ status, headers, body = rpc(writer, 'GET', 'selected')
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)[0] == 412
+ records.append(writer.stats)
+ checks.append('authored write and reply share selected input; invalid parent prevents the storage effect')
+
+ metadata = author('metadata.pure', 'on get { let o = store.read(request.key); reply(o); } ' + put)
+ with serving(binary, storage, budget=1, program=metadata) as meta:
+ status, headers, body = rpc(meta, 'GET', 'large')
+ assert status == 200 and headers['ETag'] == '"3"' and body == b''
+ assert rpc(meta, 'GET', 'absent')[0] == 404
+ assert rpc(meta, 'GET', 'broken')[0] == 500
+ assert meta.stats['peak_retained_payload_bytes'] == 0
+ records.append(meta.stats)
+ checks.append('body-free response preserves read existence and malformed-object errors')
+
+ echo = author('echo.pure', get + ' on put { let body = request.body; '
+ 'let saved = store.write(request.key, request.revision, body); reply(saved, body); }')
+ payload = bytes(range(256)) * 4096
+ with serving(binary, storage, budget=len(payload), program=echo) as echoed:
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == payload[:1]
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ assert response.read() == payload[1:]
+ response.close()
+ assert rpc(echoed, 'GET', 'binary')[2] == b'new'
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo_abort', len(payload), b'If-None-Match: *\r\n') + payload)
+ assert sock.recv(1)
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ deadline = time.monotonic() + 3
+ while rpc(echoed, 'GET', 'binary')[0] == 503:
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ assert rpc(echoed, 'GET', 'echo_abort')[2] == payload
+ records.append(echoed.stats)
+ checks.append('input-backed response survives partial send and releases on finish or abort without undoing commit')
+
+ bad = author('invalid.pure', get + get + put)
+ untouched = directory / 'must_not_exist'
+ rejected = subprocess.run([str(binary), '--program', str(bad), '--store', str(untouched)],
+ capture_output=True, text=True, timeout=10)
+ assert rejected.returncode == 2 and 'duplicate handler' in rejected.stderr and not untouched.exists()
+ checks.append('invalid authored program fails preparation before creating storage or accepting requests')
+ return prepared
+
+
+def field_connections(binary, directory, storage, records, checks):
+ program = ROOT / 'examples/selection.pure'
+ plans = {'selection': json.loads(subprocess.check_output(
+ [str(binary), '--check-program', str(program)], text=True))}
+ assert plans['selection']['runtime_view_steps'] == 1
+ assert plans['selection']['steps'][0] == {
+ 'source_step': 0, 'source': {'offset': 8, 'length': 0, 'to_end': True},
+ 'offset': {'value': 0, 'from_u32le': True}, 'length': {'value': 4, 'from_u32le': True}}
+ document = '처음🙂 Pure는 필드를 연결한다.\n끝'
+ document_file = directory / 'document.txt'
+ document_file.write_bytes(document.encode('utf-8'))
+ with serving(binary, storage, program=program) as selected:
+ command = [sys.executable, str(ROOT / 'examples/select-text.py'), str(document_file),
+ '--key', 'text_selection', '--start', '2', '--end', '12', '--url', f'http://127.0.0.1:{selected.port}']
+ result = subprocess.run(command, capture_output=True, text=True, timeout=15)
+ assert result.returncode == 0, (result.stdout, result.stderr)
+ expected = document[2:12].encode('utf-8')
+ assert json.loads(result.stdout) == {'revision': '1', 'selected': document[2:12], 'stored_bytes': len(expected)}
+ assert rpc(selected, 'GET', 'text_selection')[2] == expected
+ checks.append('text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes')
+
+ # Validation precedes the write: even a stale header cannot expose or
+ # commit partial input, and prior content/revision survive all failures.
+ invalid = [b'\0' * n for n in range(8)] + [
+ struct.pack('<II', 0xffffffff, 0) + b'abc',
+ struct.pack('<II', 0, 0xffffffff) + b'abc',
+ struct.pack('<II', 2, 2) + b'abc',
+ struct.pack('<II', 4, 0) + b'abc']
+ for payload in invalid:
+ assert rpc(selected, 'PUT', 'text_selection', payload, 1)[0] == 413
+ status, headers, body = rpc(selected, 'GET', 'text_selection')
+ assert status == 200 and headers['ETag'] == '"1"' and body == expected
+ for key, payload in [('selection_empty', struct.pack('<II', 0, 0)),
+ ('selection_end', struct.pack('<II', 3, 0) + b'abc')]:
+ assert rpc(selected, 'PUT', key, payload, 0)[0] == 200
+ assert rpc(selected, 'GET', key)[2] == b''
+ assert rpc(selected, 'PUT', 'text_selection', struct.pack('<II', 0, 3) + b'abc', 0)[0] == 412
+ checks.append('truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid')
+ records.append(selected.stats)
+
+ declaration = 'layout E { tag: bytes[3]; count: u32le; start: u32le; document: bytes; } '
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); } '
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); } '
+ reordered = directory / 'reordered.pure'
+ reordered.write_text(declaration + get + 'on put { let e = view(E, request.body); let alias = e; '
+ 'let part = range(alias.document, alias.start, alias.count); let again = part; '
+ 'let s = store.write(request.key, request.revision, again); reply(s, part); }')
+ plans['reordered'] = json.loads(subprocess.check_output([str(binary), '--check-program', str(reordered)], text=True))
+ assert plans['reordered']['runtime_view_steps'] == 1
+ with serving(binary, storage, program=reordered) as moved:
+ status, headers, body = rpc(moved, 'PUT', 'reordered', b'tag' + struct.pack('<II', 4, 2) + b'abcdefgh', 0)
+ assert status == 200 and body == b'cdef' and headers['ETag'] == '"1"'
+ assert rpc(moved, 'GET', 'reordered')[2] == b'cdef'
+ records.append(moved.stats)
+ checks.append('changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps')
+
+ unused = directory / 'unused-dynamic.pure'
+ unused.write_text(declaration + get + 'on put { let e = view(E, request.body); '
+ 'let unused = range(e.document, e.start, e.count); '
+ 'let s = store.write(request.key, request.revision, e.document); reply(s); }')
+ with serving(binary, storage, program=unused) as guarded:
+ assert rpc(guarded, 'PUT', 'unused_dynamic', b'tag' + struct.pack('<II', 4, 2) + b'abc', 0)[0] == 413
+ assert rpc(guarded, 'GET', 'unused_dynamic')[0] == 404
+ assert rpc(guarded, 'PUT', 'unused_dynamic', b'tag' + struct.pack('<II', 1, 1) + b'abc', 0)[0] == 200
+ assert rpc(guarded, 'GET', 'unused_dynamic')[2] == b'abc'
+ records.append(guarded.stats)
+ checks.append('unused dynamic field selection retains its validation before the write effect')
+
+ field_get = directory / 'field-get.pure'
+ field_get.write_text(declaration + 'on get { let o = store.read(request.key); '
+ 'let e = view(E, o.body); reply(o, e.document); } ' + put)
+ plans['field_get'] = json.loads(subprocess.check_output([str(binary), '--check-program', str(field_get)], text=True))
+ tail = '다른 길이의 문서'.encode('utf-8')
+ with serving(binary, storage, program=field_get) as writer:
+ assert rpc(writer, 'PUT', 'tail', b'tag' + struct.pack('<II', 0, 0) + tail, 0)[0] == 200
+ assert rpc(writer, 'PUT', 'bad_layout', b'short', 0)[0] == 200
+ assert rpc(writer, 'PUT', 'empty_tail', b'tag' + struct.pack('<II', 0, 0), 0)[0] == 200
+ records.append(writer.stats)
+ with serving(binary, storage, budget=len(tail), program=field_get) as reader:
+ assert rpc(reader, 'GET', 'tail')[2] == tail
+ assert rpc(reader, 'GET', 'empty_tail')[2] == b''
+ assert rpc(reader, 'GET', 'bad_layout')[0] == 413
+ assert reader.stats['peak_retained_payload_bytes'] == len(tail)
+ records.append(reader.stats)
+ checks.append('named variable tail reads use the same file version and charge only the selected suffix')
+
+ document_bytes = bytes(range(256)) * 4096
+ payload = struct.pack('<II', 16, len(document_bytes) - 32) + document_bytes
+ with serving(binary, storage, budget=len(payload), program=program) as slow:
+ with socket.create_connection(('127.0.0.1', slow.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'dynamic_slow', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == document_bytes[16:17]
+ assert rpc(slow, 'GET', 'binary')[0] == 503
+ assert response.read() == document_bytes[17:-16]
+ response.close()
+ assert rpc(slow, 'GET', 'binary')[2] == b'new'
+ assert rpc(slow, 'GET', 'dynamic_slow')[2] == document_bytes[16:-16]
+ assert slow.stats['peak_retained_payload_bytes'] == len(payload)
+ records.append(slow.stats)
+ checks.append('data-dependent response keeps and charges the original input through partial transmission')
+ return plans
+
+
+def rpc_bytes(path):
+ # CLI export is pretty JSON; wire export is compact JSON with the same model.
+ return json.dumps(json.loads(path.read_text()), ensure_ascii=False, separators=(',', ':')).encode()
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path, default=ROOT / 'build/pure-connections')
+ parser.add_argument('--output', type=Path)
+ parser.add_argument('--runtime-test', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ binary = args.server.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-connections-check-') as temporary:
+ result = check(binary, Path(temporary))
+ if args.runtime_test:
+ runtime_test = args.runtime_test.resolve()
+ tested = subprocess.run([str(runtime_test)], cwd=ROOT, capture_output=True, text=True, timeout=30)
+ assert tested.returncode == 0, (tested.stdout, tested.stderr)
+ result['execution_core'] = json.loads(tested.stdout)
+ result['execution_core_test_sha256'] = hashlib.sha256(runtime_test.read_bytes()).hexdigest()
+ result['binary_sha256'] = hashlib.sha256(binary.read_bytes()).hexdigest()
+ result['environment'] = {'platform': platform.platform(), 'machine': platform.machine(),
+ 'python': platform.python_version(), 'node': subprocess.check_output(['node', '--version'], text=True).strip()}
+ result['source_sha256'] = {str(path.relative_to(ROOT.parent.parent)): hashlib.sha256(path.read_bytes()).hexdigest()
+ for path in [*(ROOT / name for name in ('flow.c', 'flow.h', 'store.c', 'store.h', 'program.c', 'program.h',
+ 'runtime.c', 'runtime.h', 'result.h', 'evaluate.c', 'store-port.c', 'store-port.h', 'test-runtime.c',
+ 'server.c', 'check.py', 'test-flow.c', 'test-program.c', 'test-fields.c', 'Makefile',
+ 'examples/storage.pure', 'examples/excerpt.pure', 'examples/selection.pure', 'examples/select-text.py')),
+ *(WORKBENCH / name for name in ('remote.mjs', 'cli.mjs', 'web/core.wasm', 'web/runtime.mjs',
+ 'web/compiler.mjs', 'web/project.mjs', 'examples/direct.pure'))]}
+ output = json.dumps(result, ensure_ascii=False, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/evaluate.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/evaluate.c
new file mode 100644
index 0000000..3b1652f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/evaluate.c
@@ -0,0 +1,48 @@
+#include "program.h"
+#include <stdint.h>
+
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out) {
+ *out = (PureSpan){0};
+ if (region.offset > source.size) return false;
+ size_t length = region.to_end ? source.size - region.offset : region.length;
+ if (length > source.size - region.offset) return false;
+ *out = (PureSpan){length ? source.data + region.offset : NULL, length};
+ return true;
+}
+
+static bool index_read(PureIndex index, PureSpan source, size_t *out) {
+ if (!index.from_u32le) { *out = index.value; return true; }
+ if (index.value > source.size || 4 > source.size - index.value) return false;
+ const unsigned char *bytes = source.data + index.value;
+ *out = (size_t)bytes[0] | (size_t)bytes[1] << 8 | (size_t)bytes[2] << 16 | (size_t)bytes[3] << 24;
+ return true;
+}
+
+static bool resolve(PureRegion region, size_t step, PureSpan source,
+ const PureSpan *values, size_t count, PureSpan *out) {
+ if (!step) return pure_region_span(region, source, out);
+ if (step > count) return false;
+ *out = values[step - 1];
+ return true;
+}
+
+bool pure_program_input(const PureProgram *p, PureSpan source, PureSpan *write, PureSpan *reply) {
+ *write = (PureSpan){0};
+ *reply = (PureSpan){0};
+ if (source.size < p->input_required || p->input_steps > PURE_DYNAMIC_LIMIT) return false;
+ PureSpan values[PURE_DYNAMIC_LIMIT];
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ PureSpan parent;
+ size_t offset, length;
+ if (!resolve(step->source, step->source_step, source, values, i, &parent) ||
+ !index_read(step->offset, source, &offset) || !index_read(step->length, source, &length) ||
+ !pure_region_span((PureRegion){.offset = offset, .length = length}, parent, &values[i])) return false;
+ }
+ PureSpan stored, returned = {0};
+ if (!resolve(p->write, p->write_step, source, values, p->input_steps, &stored) ||
+ (p->reply_input && !resolve(p->reply, p->reply_step, source, values, p->input_steps, &returned))) return false;
+ *write = stored;
+ *reply = returned;
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/excerpt.pure b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/excerpt.pure
new file mode 100644
index 0000000..622f9bb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/excerpt.pure
@@ -0,0 +1,13 @@
+// Read bytes 32..47 of an object that must contain the complete 64-byte window.
+// Preparation keeps the size check for 16..79, and maps only 32..47 for reply.
+on get {
+ let object = store.read(request.key);
+ let window = range(object.body, 16, 64);
+ let excerpt = range(window, 16, 16);
+ reply(object, excerpt);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/select-text.py b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/select-text.py
new file mode 100644
index 0000000..ffaf80b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/select-text.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+"""Save a UTF-8 document selection through selection.pure (character indices)."""
+import argparse
+import http.client
+import json
+from pathlib import Path
+import re
+import struct
+from urllib.parse import urlsplit
+
+LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('file', type=Path)
+ parser.add_argument('--key', required=True)
+ parser.add_argument('--start', type=int, required=True, help='first Unicode code point, starting at 0')
+ parser.add_argument('--end', type=int, required=True, help='exclusive Unicode code point boundary')
+ parser.add_argument('--revision', type=int, default=0, help='0 creates; otherwise expected stored revision')
+ parser.add_argument('--url', default='http://127.0.0.1:8767')
+ args = parser.parse_args()
+ url = urlsplit(args.url)
+ try:
+ port = url.port or 80
+ except ValueError as error:
+ parser.error(str(error))
+ if (url.scheme != 'http' or url.hostname not in ['localhost', '127.0.0.1'] or
+ url.username is not None or url.password is not None or url.path not in ['', '/'] or
+ url.query or url.fragment):
+ parser.error('use a local HTTP server origin')
+ if not re.fullmatch(r'[A-Za-z0-9_-]{1,64}', args.key) or not 0 <= args.revision <= 2**63 - 1:
+ parser.error('invalid object key or revision')
+ try:
+ with args.file.open('rb') as source:
+ document = source.read(LIMIT - 8 + 1)
+ if len(document) > LIMIT - 8:
+ parser.error('document exceeds the prototype request limit')
+ text = document.decode('utf-8')
+ except (OSError, UnicodeError) as error:
+ parser.error(str(error))
+ if not 0 <= args.start <= args.end <= len(text):
+ parser.error('selection is outside the document')
+ start = len(text[:args.start].encode('utf-8'))
+ selected = text[args.start:args.end].encode('utf-8')
+ # The boundary layout is explicit; storage receives only selected bytes.
+ payload = struct.pack('<II', start, len(selected)) + document
+ headers = {'Content-Type': 'application/octet-stream'}
+ headers['If-None-Match' if args.revision == 0 else 'If-Match'] = (
+ '*' if args.revision == 0 else f'"{args.revision}"')
+ connection = http.client.HTTPConnection(url.hostname, port, timeout=12)
+ try:
+ connection.request('PUT', '/objects/' + args.key, payload, headers)
+ response = connection.getresponse()
+ body = response.read(LIMIT + 1)
+ if response.status != 200:
+ parser.error(f'storage response {response.status}: {response.getheader("X-Pure-Error")}')
+ if body != selected:
+ parser.error('response differs from the selection; check the installed program (write may have occurred)')
+ revision = response.getheader('ETag', '')
+ if not re.fullmatch(r'"[1-9][0-9]*"', revision) or int(revision[1:-1]) > 2**63 - 1:
+ parser.error('response has no valid stored revision (write may have occurred)')
+ except (OSError, http.client.HTTPException) as error:
+ parser.error(f'{error}; storage outcome is unknown if the request was sent')
+ finally:
+ connection.close()
+ print(json.dumps({'revision': revision[1:-1], 'selected': selected.decode('utf-8'),
+ 'stored_bytes': len(selected)}, ensure_ascii=False))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/selection.pure b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/selection.pure
new file mode 100644
index 0000000..7d9d4ec
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/selection.pure
@@ -0,0 +1,19 @@
+// This is an input boundary layout, not a required storage or RAM model.
+// The client sends two little-endian u32 values followed by document bytes.
+layout Selection {
+ start: u32le;
+ count: u32le;
+ document: bytes;
+}
+
+on get {
+ let saved = store.read(request.key);
+ reply(saved, saved.body);
+}
+
+on put {
+ let input = view(Selection, request.body);
+ let selected = range(input.document, input.start, input.count);
+ let saved = store.write(request.key, request.revision, selected);
+ reply(saved, selected);
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/storage.pure b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/storage.pure
new file mode 100644
index 0000000..ff54ea3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/examples/storage.pure
@@ -0,0 +1,11 @@
+// The host supplies request bytes, an object name, and the expected revision.
+// Failed storage results propagate to the host's response without executing reply.
+on get {
+ let object = store.read(request.key);
+ reply(object, object.body);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/flow.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/flow.c
new file mode 100644
index 0000000..1070c70
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/flow.c
@@ -0,0 +1,41 @@
+#include "flow.h"
+#include <assert.h>
+
+void pure_transfer_abort(PureTransfer *t) {
+ if (!t->active) return;
+ PureRelease release = t->release;
+ void *owner = t->owner;
+ *t = (PureTransfer){0};
+ if (release) release(owner);
+}
+
+static void advance(PureTransfer *t) {
+ while (t->active && t->part < 2 && t->offset == t->spans[t->part].size) {
+ t->part++;
+ t->offset = 0;
+ }
+ if (t->active && t->part == 2) pure_transfer_abort(t);
+}
+
+void pure_transfer_init(PureTransfer *t, PureSpan header, PureSpan body,
+ void *owner, PureRelease release) {
+ assert(!t->active);
+ assert((!header.size || header.data) && (!body.size || body.data));
+ *t = (PureTransfer){.spans = {header, body}, .owner = owner,
+ .release = release, .active = true};
+ advance(t);
+}
+
+PureSpan pure_transfer_next(const PureTransfer *t, size_t limit) {
+ if (!t->active) return (PureSpan){0};
+ PureSpan span = t->spans[t->part];
+ size_t remaining = span.size - t->offset;
+ return (PureSpan){span.data + t->offset, remaining < limit ? remaining : limit};
+}
+
+bool pure_transfer_consume(PureTransfer *t, size_t bytes) {
+ if (!t->active || bytes > t->spans[t->part].size - t->offset) return false;
+ t->offset += bytes;
+ advance(t);
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/flow.h b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/flow.h
new file mode 100644
index 0000000..6e27c58
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/flow.h
@@ -0,0 +1,25 @@
+#ifndef PURE_FLOW_H
+#define PURE_FLOW_H
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef struct { const unsigned char *data; size_t size; } PureSpan;
+typedef void (*PureRelease)(void *owner);
+
+/* A borrowed body stays alive until every byte is consumed or the transfer is
+ * aborted. A successful send() consumes bytes; peer receipt is a separate fact.
+ * Single owner thread; callbacks must not reenter or reuse this transfer. */
+typedef struct {
+ PureSpan spans[2];
+ size_t part, offset;
+ void *owner;
+ PureRelease release;
+ bool active;
+} PureTransfer;
+
+void pure_transfer_init(PureTransfer *, PureSpan header, PureSpan body,
+ void *owner, PureRelease);
+PureSpan pure_transfer_next(const PureTransfer *, size_t limit);
+bool pure_transfer_consume(PureTransfer *, size_t bytes);
+void pure_transfer_abort(PureTransfer *);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/program.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/program.c
new file mode 100644
index 0000000..e394d11
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/program.c
@@ -0,0 +1,357 @@
+#include "program.h"
+#include "store.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+enum { NAME = 256, NUMBER, SYMBOLS = 32, LAYOUTS = 4, FIELDS = 16 };
+typedef enum { BYTE_VALUE, RESULT_VALUE, LAYOUT_VALUE, INDEX_VALUE } ValueKind;
+typedef struct {
+ char name[32];
+ ValueKind kind;
+ PureRegion region;
+ size_t step, layout;
+ PureIndex index;
+} Symbol;
+typedef struct {
+ char name[32];
+ size_t offset, length;
+ bool number, tail;
+} Field;
+typedef struct {
+ char name[32];
+ Field fields[FIELDS];
+ size_t count, prefix;
+ bool tail;
+} Layout;
+typedef struct {
+ const char *source;
+ size_t length, at, line, token_line;
+ int token;
+ char name[32];
+ size_t number;
+ char *error;
+ size_t error_size;
+ bool failed, put, effect;
+ Symbol symbols[SYMBOLS];
+ size_t count, layout_count;
+ Layout layouts[LAYOUTS];
+ PureProgram program;
+} Parser;
+
+static bool reject(Parser *p, const char *message) {
+ if (!p->failed && p->error_size) snprintf(p->error, p->error_size, "line %zu: %s", p->token_line, message);
+ p->failed = true;
+ return false;
+}
+
+static bool letter(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
+}
+
+static bool next(Parser *p) {
+ while (p->at < p->length) {
+ char c = p->source[p->at];
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ if (c == '\n') ++p->line;
+ ++p->at;
+ } else if (c == '/' && p->at + 1 < p->length && p->source[p->at + 1] == '/') {
+ while (p->at < p->length && p->source[p->at] != '\n') ++p->at;
+ } else break;
+ }
+ p->token_line = p->line;
+ p->name[0] = 0;
+ p->token = 0;
+ if (p->at == p->length) return true;
+ char c = p->source[p->at++];
+ if (letter(c)) {
+ size_t start = p->at - 1;
+ while (p->at < p->length && (letter(p->source[p->at]) ||
+ (p->source[p->at] >= '0' && p->source[p->at] <= '9'))) ++p->at;
+ size_t size = p->at - start;
+ if (size >= sizeof(p->name)) return reject(p, "name exceeds 31 bytes");
+ memcpy(p->name, p->source + start, size);
+ p->name[size] = 0;
+ p->token = NAME;
+ } else if (c >= '0' && c <= '9') {
+ size_t value = (size_t)(c - '0');
+ while (p->at < p->length && p->source[p->at] >= '0' && p->source[p->at] <= '9') {
+ unsigned digit = (unsigned)(p->source[p->at++] - '0');
+ if (value > (SIZE_MAX - digit) / 10) return reject(p, "integer overflow");
+ value = value * 10 + digit;
+ }
+ p->number = value;
+ p->token = NUMBER;
+ } else if (c && strchr("{}().,=;:[]", c)) p->token = (unsigned char)c;
+ else return reject(p, "unexpected character");
+ return true;
+}
+
+static bool is_word(Parser *p, const char *word) {
+ return p->token == NAME && !strcmp(p->name, word);
+}
+
+static bool word(Parser *p, const char *expected) {
+ return is_word(p, expected) ? next(p) : reject(p, expected);
+}
+
+static bool token(Parser *p, int expected) {
+ return p->token == expected ? next(p) : reject(p, "unexpected token");
+}
+
+static Symbol *find(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->count; ++i)
+ if (!strcmp(name, p->symbols[i].name)) return &p->symbols[i];
+ return NULL;
+}
+
+static bool field(Parser *p, const char *object, const char *name) {
+ return word(p, object) && token(p, '.') && word(p, name);
+}
+
+static bool require_bytes(Parser *p, const Symbol *value) {
+ return value->kind == BYTE_VALUE || reject(p, "expected bytes; select a byte field");
+}
+
+static void require_length(Parser *p, size_t required) {
+ size_t *minimum = p->put ? &p->program.input_required : &p->program.read_required;
+ if (required > *minimum) *minimum = required;
+}
+
+static Layout *find_layout(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->layout_count; ++i)
+ if (!strcmp(name, p->layouts[i].name)) return &p->layouts[i];
+ return NULL;
+}
+
+static bool layout_definition(Parser *p) {
+ if (p->layout_count == LAYOUTS) return reject(p, "program exceeds 4 layouts");
+ if (!next(p)) return false;
+ if (p->token != NAME || find_layout(p, p->name)) return reject(p, "expected a unique layout name");
+ Layout *layout = &p->layouts[p->layout_count];
+ strcpy(layout->name, p->name);
+ if (!next(p) || !token(p, '{')) return false;
+ while (p->token != '}') {
+ if (layout->count == FIELDS) return reject(p, "layout exceeds 16 fields");
+ if (layout->tail) return reject(p, "variable bytes must be the last field");
+ if (p->token != NAME) return reject(p, "expected a field name");
+ for (size_t i = 0; i < layout->count; ++i)
+ if (!strcmp(layout->fields[i].name, p->name)) return reject(p, "duplicate field");
+ Field *f = &layout->fields[layout->count];
+ strcpy(f->name, p->name);
+ f->offset = layout->prefix;
+ if (!next(p) || !token(p, ':')) return false;
+ if (is_word(p, "u32le")) {
+ f->number = true;
+ f->length = 4;
+ if (!next(p)) return false;
+ } else if (is_word(p, "bytes")) {
+ if (!next(p)) return false;
+ if (p->token == '[') {
+ if (!next(p)) return false;
+ if (p->token != NUMBER) return reject(p, "fixed bytes requires a constant size");
+ f->length = p->number;
+ if (!next(p) || !token(p, ']')) return false;
+ } else { f->tail = true; layout->tail = true; }
+ } else return reject(p, "supported field types: u32le, bytes[N], bytes");
+ if (f->length > PURE_OBJECT_LIMIT - layout->prefix) return reject(p, "layout exceeds object bound");
+ layout->prefix += f->length;
+ ++layout->count;
+ if (!token(p, ';')) return false;
+ }
+ if (!layout->count) return reject(p, "empty layout");
+ ++p->layout_count;
+ return token(p, '}');
+}
+
+static bool reference(Parser *p, Symbol *out) {
+ if (is_word(p, "request")) {
+ if (!p->put) return reject(p, "request.body is only available in on put");
+ *out = (Symbol){.kind = BYTE_VALUE, .region = {.to_end = true}};
+ return field(p, "request", "body");
+ }
+ Symbol *symbol = p->token == NAME ? find(p, p->name) : NULL;
+ if (!symbol) return reject(p, "unknown value");
+ *out = *symbol;
+ if (!next(p)) return false;
+ if (p->token != '.') return true;
+ if (!next(p)) return false;
+ if (symbol->kind == RESULT_VALUE) {
+ if (p->put) return reject(p, "write result has no body; use the input value");
+ *out = (Symbol){.kind = BYTE_VALUE, .region = {.to_end = true}};
+ return word(p, "body");
+ }
+ if (symbol->kind != LAYOUT_VALUE || p->token != NAME) return reject(p, "expected a layout field");
+ Layout *layout = &p->layouts[symbol->layout];
+ Field *f = NULL;
+ for (size_t i = 0; i < layout->count; ++i)
+ if (!strcmp(p->name, layout->fields[i].name)) f = &layout->fields[i];
+ if (!f) return reject(p, "unknown layout field");
+ size_t offset = symbol->region.offset + f->offset;
+ *out = (Symbol){.kind = f->number ? INDEX_VALUE : BYTE_VALUE};
+ if (f->number) out->index = (PureIndex){.value = offset, .from_u32le = true};
+ else out->region = (PureRegion){.offset = offset,
+ .length = f->tail ? (symbol->region.to_end ? 0 : symbol->region.length - f->offset) : f->length,
+ .to_end = f->tail && symbol->region.to_end};
+ return next(p);
+}
+
+static bool byte_reference(Parser *p, Symbol *out) {
+ return reference(p, out) && require_bytes(p, out);
+}
+
+static bool index_value(Parser *p, PureIndex *out) {
+ if (p->token == NUMBER) {
+ *out = (PureIndex){.value = p->number};
+ return next(p);
+ }
+ Symbol value;
+ if (!reference(p, &value)) return false;
+ if (value.kind != INDEX_VALUE) return reject(p, "range requires an integer or u32le field");
+ *out = value.index;
+ return true;
+}
+
+static bool layout_view(Parser *p, Symbol *out) {
+ if (!next(p) || !token(p, '(')) return false;
+ Layout *layout = p->token == NAME ? find_layout(p, p->name) : NULL;
+ if (!layout) return reject(p, "unknown layout");
+ if (!next(p) || !token(p, ',')) return false;
+ Symbol source;
+ if (!byte_reference(p, &source) || !token(p, ')')) return false;
+ if (source.step) return reject(p, "layout view requires a statically located source");
+ size_t bound = source.region.to_end ? PURE_OBJECT_LIMIT - source.region.offset : source.region.length;
+ if (layout->prefix > bound) return reject(p, "layout exceeds source bound");
+ require_length(p, source.region.offset + layout->prefix);
+ *out = (Symbol){.kind = LAYOUT_VALUE, .region = source.region, .layout = (size_t)(layout - p->layouts)};
+ if (!layout->tail) { out->region.length = layout->prefix; out->region.to_end = false; }
+ return true;
+}
+
+static bool view(Parser *p, Symbol *out) {
+ if (is_word(p, "view")) return layout_view(p, out);
+ if (!is_word(p, "range")) return reference(p, out);
+ Symbol parent;
+ PureIndex offset, length;
+ if (!next(p) || !token(p, '(') || !byte_reference(p, &parent) || !token(p, ',') ||
+ !index_value(p, &offset) || !token(p, ',') || !index_value(p, &length) || !token(p, ')')) return false;
+ bool dynamic = parent.step || offset.from_u32le || length.from_u32le;
+ *out = (Symbol){.kind = BYTE_VALUE};
+ if (dynamic) {
+ if (!p->put) return reject(p, "data-dependent ranges currently require PUT input");
+ if (p->program.input_steps == PURE_DYNAMIC_LIMIT) return reject(p, "input exceeds 8 dynamic ranges");
+ if ((!offset.from_u32le && offset.value > PURE_OBJECT_LIMIT) ||
+ (!length.from_u32le && length.value > PURE_OBJECT_LIMIT)) return reject(p, "range exceeds object bound");
+ PureRangeStep *step = &p->program.steps[p->program.input_steps++];
+ *step = (PureRangeStep){.source = parent.region, .source_step = parent.step,
+ .offset = offset, .length = length};
+ out->step = p->program.input_steps;
+ } else {
+ size_t bound = parent.region.to_end ? PURE_OBJECT_LIMIT - parent.region.offset : parent.region.length;
+ if (offset.value > bound || length.value > bound - offset.value) return reject(p, "range exceeds its source bound");
+ out->region = (PureRegion){.offset = parent.region.offset + offset.value, .length = length.value};
+ require_length(p, out->region.offset + out->region.length);
+ }
+ ++p->program.range_definitions;
+ return true;
+}
+
+static bool effect(Parser *p, Symbol *out) {
+ if (p->effect) return reject(p, "only one storage effect is supported per handler");
+ if (!word(p, "store") || !token(p, '.') || !word(p, p->put ? "write" : "read") ||
+ !token(p, '(') || !field(p, "request", "key")) return false;
+ if (p->put) {
+ Symbol value;
+ if (!token(p, ',') || !field(p, "request", "revision") || !token(p, ',') ||
+ !byte_reference(p, &value)) return false;
+ p->program.write = value.region;
+ p->program.write_step = value.step;
+ }
+ if (!token(p, ')')) return false;
+ out->kind = RESULT_VALUE;
+ p->effect = true;
+ return true;
+}
+
+static bool handler(Parser *p) {
+ p->count = 0;
+ p->effect = false;
+ if (!token(p, '{')) return false;
+ while (is_word(p, "let")) {
+ if (p->put && p->effect) return reject(p, "all views must precede store.write; reply must follow it");
+ if (p->count == SYMBOLS) return reject(p, "handler exceeds 32 definitions");
+ if (!next(p)) return false;
+ if (p->token != NAME || is_word(p, "request") || is_word(p, "store") ||
+ is_word(p, "range") || is_word(p, "view")) return reject(p, "expected a non-reserved definition name");
+ if (find(p, p->name)) return reject(p, "duplicate definition");
+ char name[32];
+ strcpy(name, p->name);
+ Symbol symbol = {0};
+ if (!next(p) || !token(p, '=')) return false;
+ if (is_word(p, "store")) {
+ if (!effect(p, &symbol)) return false;
+ } else {
+ if (!view(p, &symbol)) return false;
+ ++p->program.view_definitions;
+ }
+ if (!token(p, ';')) return false;
+ strcpy(symbol.name, name);
+ p->symbols[p->count++] = symbol;
+ }
+ if (!p->effect) return reject(p, "handler requires its storage effect");
+ if (!word(p, "reply") || !token(p, '(')) return false;
+ Symbol *result = p->token == NAME ? find(p, p->name) : NULL;
+ if (!result || result->kind != RESULT_VALUE) return reject(p, "reply requires this handler's storage result");
+ if (!next(p)) return false;
+ Symbol body = {0};
+ bool has_body = p->token == ',';
+ if (has_body && (!next(p) || !byte_reference(p, &body))) return false;
+ if (!token(p, ')') || !token(p, ';') || !token(p, '}')) return false;
+ if (p->put) {
+ p->program.reply = body.region;
+ p->program.reply_step = body.step;
+ p->program.reply_input = has_body;
+ } else p->program.read = body.region;
+ return true;
+}
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size) {
+ Parser p = {.source = source, .length = length, .line = 1, .token_line = 1,
+ .error = error, .error_size = error_size};
+ if (error_size) error[0] = 0;
+ if (length > PURE_PROGRAM_LIMIT) return reject(&p, "program exceeds 16 KiB");
+ if (!next(&p)) return false;
+ while (is_word(&p, "layout")) if (!layout_definition(&p)) return false;
+ unsigned handlers = 0;
+ while (p.token) {
+ if (!word(&p, "on")) return false;
+ if (!is_word(&p, "get") && !is_word(&p, "put")) return reject(&p, "expected get or put handler");
+ p.put = is_word(&p, "put");
+ unsigned bit = p.put ? 2 : 1;
+ if (handlers & bit) return reject(&p, "duplicate handler");
+ handlers |= bit;
+ if (!next(&p) || !handler(&p)) return false;
+ }
+ if (handlers != 3) return reject(&p, "both get and put handlers are required");
+ *out = p.program; /* Invalid preparation never changes the installed plan. */
+ return true;
+}
+
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size) {
+ FILE *file = fopen(path, "rb");
+ if (!file) {
+ if (error_size) snprintf(error, error_size, "cannot open program");
+ return false;
+ }
+ char source[PURE_PROGRAM_LIMIT + 1];
+ size_t length = fread(source, 1, sizeof(source), file);
+ bool bad = ferror(file) != 0;
+ if (fclose(file)) bad = true;
+ if (bad) {
+ if (error_size) snprintf(error, error_size, "cannot read program");
+ return false;
+ }
+ return pure_program_parse(source, length, out, error, error_size);
+}
+
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/program.h b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/program.h
new file mode 100644
index 0000000..f2b5b2f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/program.h
@@ -0,0 +1,39 @@
+#ifndef PURE_PROGRAM_H
+#define PURE_PROGRAM_H
+#include "flow.h"
+
+#define PURE_PROGRAM_LIMIT 16384u
+#define PURE_DYNAMIC_LIMIT 8u
+typedef struct {
+ size_t offset, length;
+ bool to_end;
+} PureRegion;
+
+typedef struct { size_t value; bool from_u32le; } PureIndex;
+typedef struct {
+ PureRegion source;
+ size_t source_step; /* 0: source region; otherwise a preceding step + 1. */
+ PureIndex offset, length;
+} PureRangeStep;
+
+/* Prepared connections, not an instruction stream. All view definitions are
+ * checked at preparation; their root-length requirements survive elimination.
+ * Input views are evaluated before the write effect. A read still opens and
+ * validates the object even if its response has no body. */
+typedef struct {
+ PureRegion read, write, reply;
+ size_t read_required, input_required;
+ size_t view_definitions, range_definitions;
+ size_t write_step, reply_step, input_steps;
+ PureRangeStep steps[PURE_DYNAMIC_LIMIT];
+ bool reply_input;
+} PureProgram;
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size);
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size);
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out);
+/* Validates all input views, including unused dynamic views, before any effect.
+ * Returns borrowed selections; their lifetime remains that of source. */
+bool pure_program_input(const PureProgram *, PureSpan source, PureSpan *write, PureSpan *reply);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/result.h b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/result.h
new file mode 100644
index 0000000..8abb0f2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/result.h
@@ -0,0 +1,8 @@
+#ifndef PURE_RESULT_H
+#define PURE_RESULT_H
+typedef enum {
+ PURE_OK, PURE_NOT_FOUND, PURE_CONFLICT, PURE_BUSY, PURE_BUDGET,
+ PURE_LIMIT, PURE_STORE_ERROR, PURE_UNCERTAIN,
+ PURE_INVALID, PURE_DENIED, PURE_CLOSED, PURE_CANCELLED, PURE_ALLOCATION
+} PureResult;
+#endif
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/runtime.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/runtime.c
new file mode 100644
index 0000000..3b7e930
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/runtime.c
@@ -0,0 +1,265 @@
+#include "runtime.h"
+#include <string.h>
+
+#define NONE SIZE_MAX
+enum { FREE, RECEIVING, READY, RUNNING, DONE };
+
+static PureWork *lookup(PureTicket ticket, bool require_held) {
+ PureRuntime *r = ticket.runtime;
+ if (!r || ticket.slot >= r->capacity || !ticket.generation) return NULL;
+ PureWork *w = &r->work[ticket.slot];
+ if (w->state == FREE || w->generation != ticket.generation ||
+ (require_held && !w->held)) return NULL;
+ return w;
+}
+
+static bool valid_key(const char *key) {
+ if (!key || !*key) return false;
+ size_t n = 0;
+ for (; n <= 64 && key[n]; ++n) {
+ unsigned char c = (unsigned char)key[n];
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || c == '-' || c == '_')) return false;
+ }
+ return n <= 64;
+}
+
+static void dispose(PureResource *resource) {
+ PureResource old = *resource;
+ *resource = (PureResource){0};
+ if (old.release) old.release(old.allocation, old.allocation_size);
+}
+
+static void payload_release(PureRuntime *r, PureWork *w);
+
+/* Iteratively retire a chain of forwarded values. An arbitrarily long chain
+ * must not turn completion into recursive stack growth. */
+static void retire(PureRuntime *r, PureWork *w) {
+ while (w && !w->held && !w->pins) {
+ PureTicket parent = w->parent;
+ bool owned = w->charged || w->resource.release || parent.runtime;
+ dispose(&w->resource);
+ r->retained -= w->charged;
+ if (owned) ++r->releases;
+ size_t slot = (size_t)(w - r->work);
+ *w = (PureWork){.next = r->free_head};
+ r->free_head = slot;
+ --r->active;
+ if (!parent.runtime) break;
+ r = parent.runtime;
+ w = lookup(parent, false);
+ /* Pins can only be created and removed by the owner-thread core. */
+ if (!w || !w->pins) break;
+ --w->pins;
+ }
+}
+
+static void payload_release(PureRuntime *r, PureWork *w) {
+ PureTicket parent = w->parent;
+ bool owned = w->charged || w->resource.release || parent.runtime;
+ dispose(&w->resource);
+ r->retained -= w->charged;
+ w->charged = 0;
+ w->parent = (PureTicket){0};
+ if (owned) ++r->releases;
+ if (parent.runtime) {
+ PureWork *source = lookup(parent, false);
+ if (source && source->pins) { --source->pins; retire(parent.runtime, source); }
+ }
+}
+
+bool pure_runtime_init(PureRuntime *r, PureWork *work, size_t capacity,
+ const PureProgram *program, PureHost host, size_t budget) {
+ if (!r || !work || !capacity || !program) return false;
+ *r = (PureRuntime){.program = program, .host = host, .work = work,
+ .capacity = capacity, .free_head = 0, .ready_head = NONE, .ready_tail = NONE,
+ .budget = budget, .accepting = true};
+ for (size_t i = 0; i < capacity; ++i)
+ work[i] = (PureWork){.next = i + 1 < capacity ? i + 1 : NONE};
+ return true;
+}
+
+bool pure_runtime_restart(PureRuntime *r, const PureProgram *p, PureHost host, size_t budget) {
+ if (!r || !p || r->running || r->active) return false;
+ r->program = p;
+ r->host = host;
+ r->budget = budget;
+ r->accepting = true;
+ return true;
+}
+
+void pure_runtime_stop(PureRuntime *r) { if (r && !r->running) r->accepting = false; }
+
+static PureResult admission(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t bytes) {
+ if (!r || r->running || !valid_key(key) ||
+ (input != PURE_INPUT_READ && input != PURE_INPUT_WRITE) ||
+ (input == PURE_INPUT_READ ? bytes != 0 : expected < 0)) return PURE_INVALID;
+ if (!r->accepting) return PURE_CLOSED;
+ if (input == PURE_INPUT_READ ? !r->host.read : !r->host.write) return PURE_DENIED;
+ if (r->free_head == NONE) return PURE_BUSY;
+ if (r->serial == UINT64_MAX) return PURE_LIMIT;
+ if (bytes > r->budget - r->retained) { ++r->budget_rejections; return PURE_BUDGET; }
+ return PURE_OK;
+}
+
+static PureTicket occupy(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t bytes, PureResource resource) {
+ size_t slot = r->free_head;
+ PureWork *w = &r->work[slot];
+ r->free_head = w->next;
+ *w = (PureWork){.generation = ++r->serial, .next = NONE, .charged = bytes,
+ .state = RECEIVING, .held = true, .input = input, .expected = expected,
+ .resource = resource};
+ memcpy(w->key, key, strlen(key) + 1);
+ ++r->active;
+ ++r->accepted;
+ r->retained += bytes;
+ if (r->active > r->peak_active) r->peak_active = r->active;
+ if (r->retained > r->peak_retained) r->peak_retained = r->retained;
+ return (PureTicket){r, slot, w->generation};
+}
+
+bool pure_runtime_ready(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running || w->state != RECEIVING) return false;
+ PureRuntime *r = ticket.runtime;
+ w->state = READY;
+ if (r->ready_tail == NONE) r->ready_head = ticket.slot;
+ else r->work[r->ready_tail].next = ticket.slot;
+ r->ready_tail = ticket.slot;
+ return true;
+}
+
+PureResult pure_runtime_accept(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t size, PureTicket *out) {
+ if (!out) return PURE_INVALID;
+ PureResult status = admission(r, input, key, expected, size);
+ if (status != PURE_OK) return status;
+ PureResource resource = {0};
+ if (size) {
+ if (!r->host.allocate) return PURE_ALLOCATION;
+ r->running = true;
+ bool ok = r->host.allocate(r->host.context, size, &resource);
+ r->running = false;
+ if (!ok || !resource.body.data || resource.body.size != size || !resource.release) {
+ dispose(&resource);
+ return PURE_ALLOCATION;
+ }
+ }
+ *out = occupy(r, input, key, expected, size, resource);
+ if (input == PURE_INPUT_READ) pure_runtime_ready(*out);
+ return PURE_OK;
+}
+
+unsigned char *pure_runtime_ingress(PureTicket ticket, size_t *size) {
+ PureWork *w = lookup(ticket, true);
+ if (size) *size = 0;
+ if (!w || ticket.runtime->running || w->state != RECEIVING ||
+ w->input != PURE_INPUT_WRITE || w->parent.runtime) return NULL;
+ if (size) *size = w->resource.body.size;
+ return (unsigned char *)w->resource.body.data;
+}
+
+bool pure_runtime_step(PureRuntime *r) {
+ if (!r || r->running || r->ready_head == NONE) return false;
+ size_t slot = r->ready_head;
+ PureWork *w = &r->work[slot];
+ r->ready_head = w->next;
+ if (r->ready_head == NONE) r->ready_tail = NONE;
+ w->next = NONE;
+ w->state = RUNNING;
+ r->running = true;
+ PureOutcome outcome = {0};
+ if (w->input == PURE_INPUT_WRITE) {
+ PureSpan value;
+ if (!pure_program_input(r->program, w->resource.body, &value, &outcome.body))
+ outcome.status = PURE_LIMIT;
+ else outcome.status = r->host.write(r->host.context, w->key, w->expected,
+ value, &outcome.revision);
+ if (outcome.status == PURE_OK) ++r->commits;
+ else if (outcome.status == PURE_CONFLICT) ++r->conflicts;
+ } else {
+ outcome.status = r->host.read(r->host.context, w->key, r->program->read,
+ r->program->read_required, r->budget - r->retained, &w->resource, &outcome.revision);
+ if (outcome.status == PURE_OK) {
+ if (w->resource.body.size > r->budget - r->retained) outcome.status = PURE_BUDGET;
+ else if (w->resource.body.size && (!w->resource.body.data || !w->resource.release))
+ outcome.status = PURE_STORE_ERROR;
+ else {
+ w->charged = w->resource.body.size;
+ r->retained += w->charged;
+ if (r->retained > r->peak_retained) r->peak_retained = r->retained;
+ outcome.body = w->resource.body;
+ ++r->gets;
+ }
+ }
+ if (outcome.status == PURE_BUDGET) ++r->budget_rejections;
+ }
+ if (outcome.status != PURE_OK || !outcome.body.size) {
+ outcome.body = (PureSpan){0};
+ payload_release(r, w);
+ }
+ r->borrowed_output_bytes += outcome.body.size;
+ w->outcome = outcome;
+ w->state = DONE;
+ r->running = false;
+ return true;
+}
+
+bool pure_runtime_result(PureTicket ticket, PureOutcome *out) {
+ PureWork *w = lookup(ticket, true);
+ if (!out || !w || ticket.runtime->running || w->state != DONE) return false;
+ *out = w->outcome;
+ return true;
+}
+
+PureResult pure_runtime_forward(PureTicket source, PureRuntime *r,
+ const char *key, int64_t expected, PureTicket *out) {
+ PureWork *parent = lookup(source, true);
+ if (!out || !parent || source.runtime->running || parent->state != DONE ||
+ parent->outcome.status != PURE_OK) return PURE_INVALID;
+ PureResult status = admission(r, PURE_INPUT_WRITE, key, expected, parent->outcome.body.size);
+ if (status != PURE_OK) return status;
+ if (parent->pins == SIZE_MAX) return PURE_LIMIT;
+ PureTicket ticket = occupy(r, PURE_INPUT_WRITE, key, expected, parent->outcome.body.size,
+ (PureResource){.body = parent->outcome.body});
+ ++parent->pins;
+ r->work[ticket.slot].parent = source;
+ pure_runtime_ready(ticket);
+ *out = ticket;
+ return PURE_OK;
+}
+
+static void unlink_ready(PureRuntime *r, size_t slot) {
+ size_t previous = NONE;
+ for (size_t at = r->ready_head; at != NONE; at = r->work[at].next) {
+ if (at == slot) {
+ if (previous == NONE) r->ready_head = r->work[at].next;
+ else r->work[previous].next = r->work[at].next;
+ if (r->ready_tail == at) r->ready_tail = previous;
+ r->work[at].next = NONE;
+ return;
+ }
+ previous = at;
+ }
+}
+
+bool pure_runtime_cancel(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running || (w->state != RECEIVING && w->state != READY)) return false;
+ if (w->state == READY) unlink_ready(ticket.runtime, ticket.slot);
+ payload_release(ticket.runtime, w);
+ w->outcome = (PureOutcome){.status = PURE_CANCELLED};
+ w->state = DONE;
+ return true;
+}
+
+bool pure_runtime_release(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running) return false;
+ if (w->state == READY) unlink_ready(ticket.runtime, ticket.slot);
+ w->held = false;
+ retire(ticket.runtime, w);
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/runtime.h b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/runtime.h
new file mode 100644
index 0000000..4462e96
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/runtime.h
@@ -0,0 +1,86 @@
+#ifndef PURE_RUNTIME_H
+#define PURE_RUNTIME_H
+#include "program.h"
+#include "result.h"
+#include <stdint.h>
+
+/* First execution profile: authored selection -> read/conditional write ->
+ * reply. No socket, file descriptor, allocator, parser or OS type in the core.
+ * All control calls and connected domains share one owner thread. Host effects
+ * are synchronous in this profile and must not reenter the runtime. */
+typedef struct PureRuntime PureRuntime;
+typedef struct PureWork PureWork;
+typedef struct { PureRuntime *runtime; size_t slot; uint64_t generation; } PureTicket;
+typedef enum { PURE_INPUT_READ, PURE_INPUT_WRITE } PureInput;
+
+/* The host owns this resource until it successfully returns it to the core.
+ * release must end all access and free/unmap allocation exactly once. */
+typedef struct {
+ PureSpan body;
+ void *allocation;
+ size_t allocation_size;
+ void (*release)(void *allocation, size_t size);
+} PureResource;
+typedef struct {
+ void *context;
+ bool (*allocate)(void *, size_t, PureResource *);
+ PureResult (*read)(void *, const char *, PureRegion, size_t minimum,
+ size_t available, PureResource *, int64_t *revision);
+ PureResult (*write)(void *, const char *, int64_t expected,
+ PureSpan, int64_t *revision);
+} PureHost;
+typedef struct { PureResult status; int64_t revision; PureSpan body; } PureOutcome;
+
+/* Caller-provided work slots: no background thread or per-domain heap. These
+ * records are implementation storage, not an ABI or a wire representation. */
+struct PureWork {
+ uint64_t generation;
+ size_t next, charged, pins;
+ unsigned state;
+ bool held;
+ PureInput input;
+ int64_t expected;
+ char key[65];
+ PureResource resource;
+ PureTicket parent;
+ PureOutcome outcome;
+};
+struct PureRuntime {
+ const PureProgram *program;
+ PureHost host;
+ PureWork *work;
+ size_t capacity, free_head, ready_head, ready_tail;
+ size_t budget, retained, peak_retained, active, peak_active;
+ uint64_t serial, accepted, commits, gets, conflicts, budget_rejections;
+ uint64_t releases, borrowed_output_bytes;
+ bool accepting, running;
+};
+
+/* Initialize fresh storage once. Use restart, not init, to reuse a domain;
+ * the monotonic ticket sequence then survives restart. program is immutable
+ * and remains alive until all work has drained. */
+bool pure_runtime_init(PureRuntime *, PureWork *, size_t capacity,
+ const PureProgram *, PureHost, size_t budget);
+bool pure_runtime_restart(PureRuntime *, const PureProgram *, PureHost, size_t budget);
+void pure_runtime_stop(PureRuntime *); /* stop admission, allow queued work to drain */
+
+/* READ queues immediately. WRITE reserves its slot, budget and host allocation
+ * before returning. Fill ingress then publish once with ready. A partial input
+ * released without ready never executes. On error, out is unchanged. */
+PureResult pure_runtime_accept(PureRuntime *, PureInput, const char *key,
+ int64_t expected, size_t input_size, PureTicket *out);
+unsigned char *pure_runtime_ingress(PureTicket, size_t *size);
+bool pure_runtime_ready(PureTicket);
+bool pure_runtime_step(PureRuntime *); /* execute at most one ready job */
+bool pure_runtime_result(PureTicket, PureOutcome *out);
+
+/* Pin a completed reply and queue it as another domain's WRITE input, with no
+ * allocation, serialization or payload copy. Source may be released as soon
+ * as this succeeds; the core retains its backing until the consumer ends.
+ * Each domain charges its own retained input bytes as admission credits.
+ * Credits across domains are NOT distinct physical memory and must not be summed. */
+PureResult pure_runtime_forward(PureTicket source, PureRuntime *destination,
+ const char *key, int64_t expected, PureTicket *out);
+bool pure_runtime_cancel(PureTicket); /* only before execution; keeps a completion */
+bool pure_runtime_release(PureTicket); /* invalidates caller's ticket, preserves pins */
+#endif
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/server.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/server.c
new file mode 100644
index 0000000..a65b634
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/server.c
@@ -0,0 +1,368 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include "program.h"
+#include "store-port.h"
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+enum { SLOTS = 8, HEADER_LIMIT = 4096, CHUNK = 65536 };
+typedef enum { READING_HEADER, READING_BODY, WRITING } Phase;
+typedef struct Server Server;
+typedef struct {
+ int fd;
+ Phase phase;
+ uint64_t deadline;
+ char request[HEADER_LIMIT + 1], response[512], key[65];
+ size_t header_size, body_size, received;
+ unsigned char *body;
+ bool put;
+ int64_t expected;
+ PureTicket ticket;
+ PureTransfer transfer;
+ Server *server;
+} Connection;
+struct Server {
+ const char *path;
+ PureProgram program;
+ PureRuntime runtime;
+ PureWork work[SLOTS];
+ size_t budget, active, peak_active;
+ uint64_t accepted, expired, prefix_copy_bytes;
+ uint64_t timeout_ms;
+ int send_buffer;
+ Connection connections[SLOTS];
+};
+static volatile sig_atomic_t stopping;
+static void stop_server(int sig) { (void)sig; stopping = 1; }
+
+static uint64_t now_ms(void) {
+ struct timespec t;
+ if (clock_gettime(CLOCK_MONOTONIC, &t)) abort();
+ return (uint64_t)t.tv_sec * 1000 + (uint64_t)t.tv_nsec / 1000000;
+}
+
+static bool number(const char *text, uint64_t maximum, uint64_t *value) {
+ if (!*text) return false;
+ uint64_t n = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > maximum || n > (maximum - digit) / 10) return false;
+ n = n * 10 + digit;
+ }
+ *value = n;
+ return true;
+}
+
+static void release_payload(void *owner) {
+ Connection *c = owner;
+ if (c->ticket.runtime) {
+ bool released = pure_runtime_release(c->ticket);
+ assert(released);
+ (void)released;
+ }
+ c->ticket = (PureTicket){0};
+ c->body = NULL;
+}
+
+static void close_connection(Connection *c) {
+ if (c->fd < 0) return;
+ if (c->transfer.active) pure_transfer_abort(&c->transfer);
+ else release_payload(c);
+ close(c->fd);
+ --c->server->active;
+ *c = (Connection){.fd = -1};
+}
+
+static void respond(Connection *c, int status, const char *reason, const char *error,
+ int64_t revision, PureSpan body) {
+ char tag[80] = "";
+ if (revision > 0) snprintf(tag, sizeof(tag), "ETag: \"%" PRId64 "\"\r\n", revision);
+ int length = snprintf(c->response, sizeof(c->response),
+ "HTTP/1.1 %d %s\r\nContent-Length: %zu\r\nConnection: close\r\n"
+ "Content-Type: application/octet-stream\r\nCache-Control: no-store\r\n"
+ "X-Pure-Error: %s\r\n%s\r\n", status, reason, body.size, error, tag);
+ assert(length > 0 && (size_t)length < sizeof(c->response));
+ c->phase = WRITING;
+ pure_transfer_init(&c->transfer,
+ (PureSpan){(const unsigned char *)c->response, (size_t)length}, body, c, release_payload);
+}
+
+static void fail(Connection *c, int status, const char *reason, const char *error) {
+ /* No outstanding backend access on the owner thread at this point. */
+ release_payload(c);
+ respond(c, status, reason, error, 0, (PureSpan){0});
+}
+
+static void answer(Connection *c, PureOutcome result) {
+ switch (result.status) {
+ case PURE_OK: respond(c, 200, "OK", "none", result.revision, result.body); break;
+ case PURE_NOT_FOUND: fail(c, 404, "Not Found", "not_found"); break;
+ case PURE_CONFLICT:
+ respond(c, 412, "Precondition Failed", "conflict", result.revision, (PureSpan){0}); break;
+ case PURE_BUSY: fail(c, 503, "Service Unavailable", "store_busy"); break;
+ case PURE_BUDGET: fail(c, 503, "Service Unavailable", "payload_budget"); break;
+ case PURE_ALLOCATION: fail(c, 503, "Service Unavailable", "allocation"); break;
+ case PURE_CLOSED: fail(c, 503, "Service Unavailable", "stopped"); break;
+ case PURE_DENIED: fail(c, 403, "Forbidden", "denied"); break;
+ case PURE_LIMIT: fail(c, 413, "Content Too Large", "limit"); break;
+ case PURE_UNCERTAIN: fail(c, 500, "Internal Server Error", "durability_unknown"); break;
+ default: fail(c, 500, "Internal Server Error", "storage"); break;
+ }
+}
+
+static void run_request(Connection *c) {
+ if (c->put && !pure_runtime_ready(c->ticket)) abort();
+ PureOutcome result;
+ while (!pure_runtime_result(c->ticket, &result))
+ if (!pure_runtime_step(&c->server->runtime)) abort();
+ c->body = NULL; /* Core now owns input until all consumers release it. */
+ answer(c, result);
+}
+
+/* Deliberately bounded HTTP/1.1 subset: one GET/PUT, Content-Length, close.
+ * No transfer coding, pipelining, trailers, Expect, URL decoding, or proxying. */
+static bool parse_header(Connection *c, size_t end) {
+ for (size_t i = 0; i < end; ++i) {
+ unsigned char b = (unsigned char)c->request[i];
+ if ((b < 32 && b != '\r' && b != '\n' && b != '\t') || b == 127) return false;
+ }
+ char *line = c->request, *next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *path = strchr(line, ' ');
+ if (!path) return false;
+ *path++ = 0;
+ if (strcmp(line, "PUT") == 0) c->put = true;
+ else if (strcmp(line, "GET") != 0) return false;
+ char *version = strchr(path, ' ');
+ if (!version) return false;
+ *version++ = 0;
+ if (strcmp(version, "HTTP/1.1") || strncmp(path, "/objects/", 9)) return false;
+ const char *key = path + 9;
+ size_t key_size = strlen(key);
+ if (!key_size || key_size > 64) return false;
+ for (size_t i = 0; i < key_size; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ memcpy(c->key, key, key_size + 1);
+ bool length_seen = false, condition_seen = false, host_seen = false;
+ line = next + 2;
+ while (*line != '\r') {
+ next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *value = strchr(line, ':');
+ if (!value || value == line) return false;
+ *value++ = 0;
+ for (char *p = line; *p; ++p)
+ if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') || *p == '-')) return false;
+ while (*value == ' ' || *value == '\t') ++value;
+ char *tail = value + strlen(value);
+ while (tail > value && (tail[-1] == ' ' || tail[-1] == '\t')) *--tail = 0;
+ if (strchr(value, '\r') || strchr(value, '\n')) return false;
+ uint64_t n;
+ if (!strcasecmp(line, "Content-Length")) {
+ if (length_seen || !number(value, SIZE_MAX, &n)) return false;
+ length_seen = true;
+ c->body_size = (size_t)n;
+ } else if (!strcasecmp(line, "Host")) {
+ if (host_seen || !*value) return false;
+ host_seen = true;
+ } else if (!strcasecmp(line, "If-Match")) {
+ if (condition_seen || tail - value < 3 || *value != '"' || tail[-1] != '"') return false;
+ tail[-1] = 0;
+ if (!number(value + 1, INT64_MAX, &n) || !n) return false;
+ c->expected = (int64_t)n;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "If-None-Match")) {
+ if (condition_seen || strcmp(value, "*")) return false;
+ c->expected = 0;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "Transfer-Encoding") || !strcasecmp(line, "Expect")) return false;
+ line = next + 2;
+ }
+ return host_seen && (c->put ? length_seen && condition_seen : !condition_seen && c->body_size == 0);
+}
+
+static void read_connection(Connection *c) {
+ if (c->phase == READING_HEADER) {
+ ssize_t n = recv(c->fd, c->request + c->header_size, HEADER_LIMIT - c->header_size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->header_size += (size_t)n;
+ c->request[c->header_size] = 0;
+ /* Scan by byte count, so embedded NUL cannot hide a terminator. */
+ size_t end = 0;
+ for (size_t i = 3; i < c->header_size; ++i)
+ if (!memcmp(c->request + i - 3, "\r\n\r\n", 4)) { end = i + 1; break; }
+ if (!end) {
+ if (c->header_size == HEADER_LIMIT) fail(c, 431, "Request Header Fields Too Large", "headers");
+ return;
+ }
+ size_t prefix = c->header_size - end;
+ if (!parse_header(c, end)) { fail(c, 400, "Bad Request", "request"); return; }
+ if (c->body_size > PURE_OBJECT_LIMIT) { fail(c, 413, "Content Too Large", "limit"); return; }
+ if (prefix > c->body_size) { fail(c, 400, "Bad Request", "extra_body"); return; }
+ PureResult admitted = pure_runtime_accept(&c->server->runtime,
+ c->put ? PURE_INPUT_WRITE : PURE_INPUT_READ, c->key, c->expected, c->body_size, &c->ticket);
+ if (admitted != PURE_OK) { answer(c, (PureOutcome){.status = admitted}); return; }
+ if (!c->put) { run_request(c); return; }
+ c->body = pure_runtime_ingress(c->ticket, NULL);
+ if (prefix) memcpy(c->body, c->request + end, prefix);
+ c->server->prefix_copy_bytes += prefix;
+ c->received = prefix;
+ c->phase = READING_BODY;
+ if (c->received == c->body_size) run_request(c);
+ } else {
+ size_t remaining = c->body_size - c->received;
+ ssize_t n = recv(c->fd, c->body + c->received, remaining < CHUNK ? remaining : CHUNK, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->received += (size_t)n;
+ if (c->received == c->body_size) run_request(c);
+ }
+}
+
+static void write_connection(Connection *c) {
+ PureSpan span = pure_transfer_next(&c->transfer, CHUNK);
+ ssize_t n = send(c->fd, span.data, span.size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ if (!pure_transfer_consume(&c->transfer, (size_t)n)) abort();
+ if (!c->transfer.active) close_connection(c);
+}
+
+static bool nonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
+}
+
+int main(int argc, char **argv) {
+ Server server = {.budget = 4u * 1024u * 1024u, .timeout_ms = 10000};
+ unsigned port = 8767;
+ const char *program_path = NULL;
+ bool explain = argc == 3 && !strcmp(argv[1], "--check-program");
+ char program_error[160];
+ if (explain) program_path = argv[2];
+ for (int i = 1; !explain && i < argc; i += 2) {
+ if (i + 1 == argc) goto usage;
+ uint64_t value;
+ if (!strcmp(argv[i], "--store")) server.path = argv[i + 1];
+ else if (!strcmp(argv[i], "--program")) program_path = argv[i + 1];
+ else if (!strcmp(argv[i], "--port") && number(argv[i + 1], 65535, &value)) port = (unsigned)value;
+ else if (!strcmp(argv[i], "--budget") && number(argv[i + 1], SIZE_MAX, &value) && value) server.budget = (size_t)value;
+ else if (!strcmp(argv[i], "--timeout-ms") && number(argv[i + 1], 3600000, &value) && value) server.timeout_ms = value;
+ else if (!strcmp(argv[i], "--send-buffer") && number(argv[i + 1], INT32_MAX, &value)) server.send_buffer = (int)value;
+ else goto usage;
+ }
+ if (!program_path || (!explain && !server.path)) goto usage;
+ if (!pure_program_load(program_path, &server.program, program_error, sizeof(program_error))) {
+ fprintf(stderr, "Program: %s\n", program_error); return 2;
+ }
+ if (explain) {
+ PureProgram *p = &server.program;
+ printf("{\"read\":{\"to_end\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"write\":{\"to_end\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"reply_input\":%s,\"view_definitions\":%zu,\"range_definitions\":%zu,"
+ "\"runtime_view_steps\":%zu,\"write_step\":%zu,\"reply_step\":%zu,\"prepared_program_bytes\":%zu,\"steps\":[",
+ p->read.to_end ? "true" : "false", p->read.offset, p->read.length, p->read_required,
+ p->write.to_end ? "true" : "false", p->write.offset, p->write.length, p->input_required,
+ p->reply_input ? "true" : "false", p->view_definitions, p->range_definitions,
+ p->input_steps, p->write_step, p->reply_step, sizeof(*p));
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ printf("%s{\"source_step\":%zu,\"source\":{\"offset\":%zu,\"length\":%zu,\"to_end\":%s},"
+ "\"offset\":{\"value\":%zu,\"from_u32le\":%s},\"length\":{\"value\":%zu,\"from_u32le\":%s}}",
+ i ? "," : "", step->source_step, step->source.offset, step->source.length,
+ step->source.to_end ? "true" : "false", step->offset.value, step->offset.from_u32le ? "true" : "false",
+ step->length.value, step->length.from_u32le ? "true" : "false");
+ }
+ puts("]}");
+ return 0;
+ }
+ if (pure_store_init(server.path) != PURE_OK) { fputs("Cannot initialize byte store directory\n", stderr); return 1; }
+ if (!pure_runtime_init(&server.runtime, server.work, SLOTS, &server.program,
+ pure_store_host(server.path), server.budget)) return 1;
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, stop_server);
+ signal(SIGTERM, stop_server);
+ int listener = socket(AF_INET, SOCK_STREAM, 0);
+ if (listener < 0) { perror("socket"); return 1; }
+ int one = 1;
+ setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ struct sockaddr_in address = {.sin_family = AF_INET, .sin_port = htons((uint16_t)port),
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ if (bind(listener, (struct sockaddr *)&address, sizeof(address)) || listen(listener, SLOTS) || !nonblocking(listener)) {
+ perror("listen"); close(listener); return 1;
+ }
+ socklen_t address_size = sizeof(address);
+ if (getsockname(listener, (struct sockaddr *)&address, &address_size)) { close(listener); return 1; }
+ for (size_t i = 0; i < SLOTS; ++i) server.connections[i].fd = -1;
+ printf("{\"port\":%u,\"storage\":\"immutable-byte-extents-v1\"}\n", ntohs(address.sin_port));
+ fflush(stdout);
+ while (!stopping) {
+ struct pollfd polls[SLOTS + 1] = {{.fd = server.active < SLOTS ? listener : -1, .events = POLLIN}};
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ polls[i + 1] = (struct pollfd){.fd = c->fd, .events = c->phase == WRITING ? POLLOUT : POLLIN};
+ }
+ int ready = poll(polls, SLOTS + 1, 50);
+ if (ready < 0 && errno != EINTR) { perror("poll"); stopping = 1; }
+ uint64_t now = now_ms();
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ if (c->fd < 0) continue;
+ if (now >= c->deadline) { ++server.expired; close_connection(c); continue; }
+ short events = polls[i + 1].revents;
+ if (events & (POLLERR | POLLNVAL)) { close_connection(c); continue; }
+ if (events & (POLLIN | POLLOUT | POLLHUP)) {
+ if (c->phase == WRITING) write_connection(c); else read_connection(c);
+ }
+ }
+ if (!stopping && (polls[0].revents & POLLIN)) {
+ int fd = accept(listener, NULL, NULL);
+ if (fd < 0) continue;
+ if (!nonblocking(fd)) { close(fd); continue; }
+ if (server.send_buffer) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &server.send_buffer, sizeof(server.send_buffer));
+ for (size_t i = 0; i < SLOTS; ++i) if (server.connections[i].fd < 0) {
+ server.connections[i] = (Connection){.fd = fd, .server = &server, .deadline = now_ms() + server.timeout_ms};
+ ++server.active;
+ ++server.accepted;
+ if (server.active > server.peak_active) server.peak_active = server.active;
+ break;
+ }
+ }
+ }
+ close(listener);
+ pure_runtime_stop(&server.runtime);
+ for (size_t i = 0; i < SLOTS; ++i) close_connection(&server.connections[i]);
+ fprintf(stderr, "{\"active\":%zu,\"retained_payload_bytes\":%zu,\"peak_retained_payload_bytes\":%zu,"
+ "\"payload_budget\":%zu,\"peak_connections\":%zu,\"accepted\":%" PRIu64 ",\"commits\":%" PRIu64 ","
+ "\"gets\":%" PRIu64 ",\"conflicts\":%" PRIu64 ",\"budget_rejections\":%" PRIu64 ","
+ "\"expired\":%" PRIu64 ",\"releases\":%" PRIu64 ",\"ingress_prefix_copy_bytes\":%" PRIu64 ","
+ "\"borrowed_output_bytes\":%" PRIu64 ",\"server_structure_bytes\":%zu}\n",
+ server.active, server.runtime.retained, server.runtime.peak_retained, server.budget, server.peak_active,
+ server.accepted, server.runtime.commits, server.runtime.gets, server.runtime.conflicts, server.runtime.budget_rejections,
+ server.expired, server.runtime.releases, server.prefix_copy_bytes, server.runtime.borrowed_output_bytes, sizeof(server));
+ return 0;
+usage:
+ fputs("pure-connections --program FILE --store DIRECTORY [--port 8767] [--budget BYTES] [--timeout-ms 10000] [--send-buffer BYTES]\n"
+ "pure-connections --check-program FILE\n", stderr);
+ return 2;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store-port.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store-port.c
new file mode 100644
index 0000000..06ff114
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store-port.c
@@ -0,0 +1,39 @@
+#include "store-port.h"
+#include "store.h"
+#include <stdlib.h>
+#include <sys/mman.h>
+
+static void free_memory(void *data, size_t size) { (void)size; free(data); }
+static void unmap_memory(void *data, size_t size) { if (size) munmap(data, size); }
+
+static bool allocate(void *context, size_t size, PureResource *out) {
+ (void)context;
+ void *data = malloc(size);
+ if (!data) return false;
+ *out = (PureResource){.body = {data, size}, .allocation = data,
+ .allocation_size = size, .release = free_memory};
+ return true;
+}
+
+static PureResult read_value(void *context, const char *key, PureRegion region,
+ size_t minimum, size_t available, PureResource *out, int64_t *revision) {
+ PureStoredView view = {0};
+ PureResult result = pure_store_select(context, key, region.offset, region.length,
+ region.to_end, minimum, available, &view);
+ if (result == PURE_OK) {
+ *out = (PureResource){.body = view.body, .allocation = view.mapping,
+ .allocation_size = view.mapped_size, .release = view.mapped_size ? unmap_memory : NULL};
+ *revision = view.revision;
+ }
+ return result;
+}
+
+static PureResult write_value(void *context, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ return pure_store_put(context, key, expected, body, revision);
+}
+
+PureHost pure_store_host(const char *path) {
+ return (PureHost){.context = (void *)path, .allocate = allocate,
+ .read = read_value, .write = write_value};
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store-port.h b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store-port.h
new file mode 100644
index 0000000..4c0d49d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store-port.h
@@ -0,0 +1,6 @@
+#ifndef PURE_STORE_PORT_H
+#define PURE_STORE_PORT_H
+#include "runtime.h"
+/* The path remains alive for the domain's complete lifetime, including pins. */
+PureHost pure_store_host(const char *path);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store.c
new file mode 100644
index 0000000..1c13a80
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store.c
@@ -0,0 +1,228 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Immutable extent envelope: marker, little-endian u64 revision and payload
+ * length, then unchanged caller bytes. Single-threaded control API; cooperating
+ * processes serialize publication using .writer.lock. */
+enum { HEADER_BYTES = 24 };
+static const unsigned char magic[8] = {'P','U','R','E','B','0','0','1'};
+static uint64_t temporary_sequence;
+
+static bool fault(PureStoreStage stage) {
+#ifdef PURE_STORE_TEST
+ if (pure_store_test_fault(stage)) { errno = EIO; return true; }
+#else
+ (void)stage;
+#endif
+ return false;
+}
+
+static bool file_name(const char *key, char name[72]) {
+ if (!key) return false;
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ snprintf(name, 72, "obj-%s", key);
+ return true;
+}
+
+static uint64_t decode64(const unsigned char *bytes) {
+ uint64_t value = 0;
+ for (unsigned i = 0; i < 8; ++i) value |= (uint64_t)bytes[i] << (8 * i);
+ return value;
+}
+
+static void encode64(unsigned char *bytes, uint64_t value) {
+ for (unsigned i = 0; i < 8; ++i) bytes[i] = (unsigned char)(value >> (8 * i));
+}
+
+static bool sync_fd(int fd) {
+ int rc;
+ do { rc = fsync(fd); } while (rc && errno == EINTR);
+ return rc == 0;
+}
+
+static bool write_bytes(int fd, const unsigned char *bytes, size_t length) {
+ while (length) {
+ ssize_t n = write(fd, bytes, length);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ bytes += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static bool read_header(int fd, int64_t *revision, size_t *length) {
+ struct stat info;
+ if (fstat(fd, &info) || !S_ISREG(info.st_mode)) return false;
+ unsigned char header[HEADER_BYTES];
+ size_t used = 0;
+ while (used < sizeof(header)) {
+ ssize_t n = pread(fd, header + used, sizeof(header) - used, (off_t)used);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ used += (size_t)n;
+ }
+ uint64_t version = decode64(header + 8), size = decode64(header + 16);
+ if (memcmp(header, magic, sizeof(magic)) || !version || version > INT64_MAX ||
+ size > PURE_OBJECT_LIMIT || info.st_size != (off_t)(HEADER_BYTES + size)) return false;
+ *revision = (int64_t)version;
+ *length = (size_t)size;
+ return true;
+}
+
+PureResult pure_store_init(const char *path) {
+ if (!path || !*path) return PURE_STORE_ERROR;
+ bool created = mkdir(path, 0700) == 0;
+ if (!created && errno != EEXIST) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR; /* Never reinterpret an old DB file. */
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600);
+ struct stat info;
+ bool ok = lock >= 0 && fstat(lock, &info) == 0 && S_ISREG(info.st_mode) && sync_fd(lock);
+ if (lock >= 0) close(lock);
+ if (ok) ok = sync_fd(directory);
+ close(directory);
+ if (!ok) return PURE_STORE_ERROR;
+ if (created) {
+ char *parent = strdup(path);
+ if (!parent) return PURE_STORE_ERROR;
+ size_t length = strlen(parent);
+ while (length > 1 && parent[length - 1] == '/') parent[--length] = 0;
+ char *slash = strrchr(parent, '/');
+ if (!slash) strcpy(parent, ".");
+ else if (slash == parent) parent[1] = 0;
+ else *slash = 0;
+ int fd = open(parent, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ free(parent);
+ ok = fd >= 0 && sync_fd(fd);
+ if (fd >= 0) close(fd);
+ }
+ return ok ? PURE_OK : PURE_STORE_ERROR;
+}
+
+void pure_store_release(PureStoredView *view) {
+ if (view->mapped_size) munmap(view->mapping, view->mapped_size);
+ *view = (PureStoredView){0};
+}
+
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out) {
+ *out = (PureStoredView){0};
+ char name[72];
+ if (!file_name(key, name)) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ int cause = errno;
+ close(directory);
+ if (fd < 0) return cause == ENOENT ? PURE_NOT_FOUND : PURE_STORE_ERROR;
+ int64_t revision;
+ size_t size;
+ PureResult result = PURE_STORE_ERROR;
+ if (!read_header(fd, &revision, &size)) goto finish;
+ if (size < minimum) { result = PURE_LIMIT; goto finish; }
+ if (offset > size) { result = PURE_LIMIT; goto finish; }
+ if (whole) length = size - offset;
+ if (offset > size || length > size - offset) { result = PURE_LIMIT; goto finish; }
+ if (length > available) { result = PURE_BUDGET; goto finish; }
+ if (length) {
+ long page = sysconf(_SC_PAGESIZE);
+ if (page <= 0) goto finish;
+ size_t start = HEADER_BYTES + offset;
+ size_t aligned = start - start % (size_t)page;
+ size_t prefix = start - aligned;
+ size_t mapped_size = prefix + length;
+ void *mapping = mmap(NULL, mapped_size, PROT_READ, MAP_PRIVATE, fd, (off_t)aligned);
+ if (mapping == MAP_FAILED) goto finish;
+ out->mapping = mapping;
+ out->mapped_size = mapped_size;
+ out->body = (PureSpan){(const unsigned char *)mapping + prefix, length};
+ }
+ out->revision = revision;
+ out->object_size = size;
+ result = PURE_OK;
+finish:
+ close(fd); /* The mapping retains this immutable file version after rename. */
+ return result;
+}
+
+PureResult pure_store_get(const char *path, const char *key, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, 0, 0, true, 0, available, out);
+}
+
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, offset, length, false, 0, available, out);
+}
+
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ *revision = 0;
+ char name[72], temporary[96] = "";
+ if (!file_name(key, name) || (body.size && !body.data)) return PURE_STORE_ERROR;
+ if (body.size > PURE_OBJECT_LIMIT || expected < 0) return PURE_LIMIT;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_NOFOLLOW | O_CLOEXEC);
+ int fd = -1;
+ PureResult result = PURE_STORE_ERROR;
+ struct stat info;
+ if (lock < 0 || fstat(lock, &info) || !S_ISREG(info.st_mode)) goto finish;
+ struct flock hold = {.l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0};
+ if (fcntl(lock, F_SETLK, &hold)) {
+ if (errno == EACCES || errno == EAGAIN) result = PURE_BUSY;
+ goto finish;
+ }
+ fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (fd >= 0) {
+ size_t size;
+ if (!read_header(fd, revision, &size)) goto finish;
+ close(fd);
+ fd = -1;
+ } else if (errno != ENOENT) goto finish;
+ if (*revision != expected) { result = PURE_CONFLICT; goto finish; }
+ if (*revision == INT64_MAX) { result = PURE_LIMIT; goto finish; }
+ for (unsigned attempt = 0; attempt < 64; ++attempt) {
+ if (temporary_sequence == UINT64_MAX) goto finish;
+ snprintf(temporary, sizeof(temporary), ".pending-%ld-%" PRIu64, (long)getpid(), ++temporary_sequence);
+ fd = openat(directory, temporary, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
+ if (fd >= 0) break;
+ temporary[0] = 0; /* Never remove an existing file on a name collision. */
+ if (errno != EEXIST) goto finish;
+ }
+ if (fd < 0) goto finish;
+ unsigned char header[HEADER_BYTES];
+ memcpy(header, magic, sizeof(magic));
+ encode64(header + 8, (uint64_t)*revision + 1);
+ encode64(header + 16, body.size);
+ if (!write_bytes(fd, header, sizeof(header)) || fault(PURE_AFTER_HEADER) ||
+ !write_bytes(fd, body.data, body.size) || fault(PURE_BEFORE_FILE_SYNC) || !sync_fd(fd)) goto finish;
+ int close_result = close(fd);
+ fd = -1;
+ if (close_result || fault(PURE_BEFORE_RENAME) || renameat(directory, temporary, directory, name)) goto finish;
+ temporary[0] = 0; /* Published: a later sync failure does not roll it back. */
+ ++*revision;
+ result = fault(PURE_BEFORE_DIR_SYNC) || !sync_fd(directory) ? PURE_UNCERTAIN : PURE_OK;
+finish:
+ if (fd >= 0) close(fd);
+ if (*temporary) unlinkat(directory, temporary, 0);
+ if (lock >= 0) close(lock);
+ close(directory);
+ return result;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store.h b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store.h
new file mode 100644
index 0000000..1c0e054
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/store.h
@@ -0,0 +1,37 @@
+#ifndef PURE_STORE_H
+#define PURE_STORE_H
+#include "flow.h"
+#include "result.h"
+#include <stdint.h>
+
+#define PURE_OBJECT_LIMIT ((2u * 6u + 32u) * 32768u + 8192u)
+typedef struct {
+ void *mapping;
+ size_t mapped_size, object_size;
+ PureSpan body;
+ int64_t revision;
+} PureStoredView;
+
+PureResult pure_store_init(const char *path);
+PureResult pure_store_get(const char *path, const char *key, size_t available,
+ PureStoredView *out);
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out);
+/* Inspect once: guards and mapping refer to the same immutable file version.
+ * minimum preserves bounds checks from eliminated intermediate views.
+ * whole selects the suffix starting at offset; otherwise length is exact. */
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out);
+void pure_store_release(PureStoredView *);
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision);
+
+/* Fault hooks exist only in the separately built unit-test binary. */
+typedef enum {
+ PURE_AFTER_HEADER, PURE_BEFORE_FILE_SYNC, PURE_BEFORE_RENAME, PURE_BEFORE_DIR_SYNC
+} PureStoreStage;
+#ifdef PURE_STORE_TEST
+int pure_store_test_fault(PureStoreStage stage);
+#endif
+#endif
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-fields.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-fields.c
new file mode 100644
index 0000000..63dfc3e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-fields.c
@@ -0,0 +1,153 @@
+#include "program.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static const char layout[] = "layout Envelope { marker: bytes[1]; start: u32le; count: u32le; text: bytes; }";
+static PureProgram parse(const char *source) {
+ PureProgram p;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &p, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return p;
+}
+static void invalid(const char *source) {
+ PureProgram p;
+ memset(&p, 0x5a, sizeof(p));
+ unsigned char before[sizeof(p)];
+ memcpy(before, &p, sizeof(p));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(*error && !memcmp(before, &p, sizeof(p)));
+}
+static void encode(unsigned char *at, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) at[i] = (unsigned char)(value >> (8 * i));
+}
+int main(void) {
+ char source[8000];
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let alias = input; let start = alias.start; let text = alias.text; "
+ "let selected = range(text, start, alias.count); let result = selected; "
+ "let saved = store.write(request.key, request.revision, result); reply(saved, selected); }", layout, get);
+ PureProgram p = parse(source);
+ CHECK(p.input_steps == 1 && p.input_required == 9 && p.write_step == 1 && p.reply_step == 1);
+ CHECK(p.steps[0].source.offset == 9 && p.steps[0].source.to_end);
+ CHECK(p.steps[0].offset.value == 1 && p.steps[0].offset.from_u32le);
+ CHECK(p.steps[0].length.value == 5 && p.steps[0].length.from_u32le);
+ unsigned char bytes[609];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 13);
+ PureSpan stored, returned;
+ for (size_t n = 0; n < 9; ++n) {
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, n}, &stored, &returned));
+ CHECK(!stored.size && !returned.size);
+ }
+ const uint32_t offsets[] = {0, 1, 255, 257, 599, 600, 601, UINT32_MAX};
+ const uint32_t counts[] = {0, 1, 2, 260, 600, UINT32_MAX};
+ size_t comparisons = 0;
+ for (size_t i = 0; i < sizeof(offsets) / sizeof(*offsets); ++i)
+ for (size_t j = 0; j < sizeof(counts) / sizeof(*counts); ++j) {
+ uint32_t start = offsets[i], count = counts[j];
+ encode(bytes + 1, start);
+ encode(bytes + 5, count);
+ bool expected = start <= 600 && count <= 600 - start;
+ CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned) == expected);
+ if (expected) {
+ CHECK(stored.size == count && returned.size == count && stored.data == returned.data);
+ CHECK(!count || stored.data == bytes + 9 + start);
+ } else CHECK(!stored.size && !returned.size);
+ ++comparisons;
+ }
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let first = range(input.text, input.start, input.count); let second = range(first, 1, 2); "
+ "let saved = store.write(request.key, request.revision, second); reply(saved, second); }", layout, get);
+ p = parse(source);
+ CHECK(p.input_steps == 2 && p.steps[1].source_step == 1);
+ encode(bytes + 1, 3); encode(bytes + 5, 4);
+ CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+ CHECK(stored.size == 2 && stored.data == bytes + 13);
+ encode(bytes + 5, 2);
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let unused = range(input.text, input.start, input.count); "
+ "let saved = store.write(request.key, request.revision, input.text); reply(saved); }", layout, get);
+ p = parse(source);
+ encode(bytes + 1, UINT32_MAX);
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+
+ snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); "
+ "let input = view(Envelope, o.body); reply(o, input.text); } %s", layout, put);
+ p = parse(source);
+ CHECK(p.read.to_end && p.read.offset == 9 && p.read_required == 9 && !p.input_steps);
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let selection = range(input.text, 2, 3); let saved = store.write(request.key, request.revision, selection); reply(saved); }", layout, get);
+ p = parse(source);
+ CHECK(!p.input_steps && p.write.offset == 11 && p.write.length == 3 && p.input_required == 14);
+ snprintf(source, sizeof(source), "layout Empty { body: bytes; } %s on put { let input = view(Empty, request.body); "
+ "let saved = store.write(request.key, request.revision, input.body); reply(saved, input.body); }", get);
+ p = parse(source);
+ CHECK(pure_program_input(&p, (PureSpan){0}, &stored, &returned) && !stored.size && !returned.size);
+
+ const char *bad_layout[] = {
+ "layout E {}", "layout E { x: bytes; y: u32le; }", "layout E { x: u32le; x: bytes; }",
+ "layout E { x: bytes[1449985]; }", "layout E { x: bytes[1449984]; y: u32le; }",
+ "layout E { x: bytes[184467440737095516160]; }", "layout E { x: u64le; }",
+ "layout E { x: u32le; } layout E { y: bytes; }"
+ };
+ for (size_t i = 0; i < sizeof(bad_layout) / sizeof(*bad_layout); ++i) {
+ snprintf(source, sizeof(source), "%s %s %s", bad_layout[i], get, put); invalid(source);
+ }
+ const char *bad_input[] = {
+ "let input = view(Missing, request.body);",
+ "let input = view(Envelope, request.body); let x = input.missing;",
+ "let input = view(Envelope, request.body); let x = range(input.text, input.text, 1);",
+ "let short = range(request.body, 0, 8); let input = view(Envelope, short);",
+ "let input = view(Envelope, request.body); let x = range(input.text, input.start, 20); let y = view(Envelope, x);"
+ };
+ for (size_t i = 0; i < sizeof(bad_input) / sizeof(*bad_input); ++i) {
+ snprintf(source, sizeof(source), "%s %s on put { %s let saved = store.write(request.key, request.revision, request.body); reply(saved); }", layout, get, bad_input[i]);
+ invalid(source);
+ }
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let saved = store.write(request.key, request.revision, input.start); reply(saved); }", layout, get);
+ invalid(source);
+ snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); let input = view(Envelope, o.body); "
+ "let x = range(input.text, input.start, input.count); reply(o, x); } %s", layout, put);
+ invalid(source);
+ for (size_t count = 8; count <= 9; ++count) {
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); ", layout, get);
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let v%zu = range(input.text, input.start, input.count); ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let saved = store.write(request.key, request.revision, input.text); reply(saved); }");
+ if (count == 8) CHECK(parse(source).input_steps == 8); else invalid(source);
+ }
+ for (size_t count = 4; count <= 5; ++count) {
+ source[0] = 0;
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "layout L%zu { body: bytes; } ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "%s %s", get, put);
+ if (count == 4) (void)parse(source); else invalid(source);
+ }
+ for (size_t count = 16; count <= 17; ++count) {
+ strcpy(source, "layout L { ");
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "f%zu: u32le; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "} %s %s", get, put);
+ if (count == 16) (void)parse(source); else invalid(source);
+ }
+ printf("{\"fields\":\"named-layouts-unaligned-u32le-tail-dynamic-ranges-aliases-failures-limits\","
+ "\"data_boundary_cases\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-flow.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-flow.c
new file mode 100644
index 0000000..5ff028d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-flow.c
@@ -0,0 +1,183 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static int failed_stage = -1;
+static bool crash_at_stage;
+int pure_store_test_fault(PureStoreStage stage) {
+ if ((int)stage != failed_stage) return 0;
+ if (crash_at_stage) _exit(77);
+ return 1;
+}
+typedef struct { unsigned char *bytes; unsigned releases; } Owner;
+static void release(void *raw) {
+ Owner *owner = raw;
+ free(owner->bytes);
+ owner->bytes = NULL;
+ ++owner->releases;
+}
+
+static void transfers(void) {
+ Owner owner = {.bytes = malloc(5)};
+ CHECK(owner.bytes);
+ memcpy(owner.bytes, "a\0bcd", 5);
+ PureTransfer transfer = {0};
+ pure_transfer_init(&transfer, (PureSpan){(const unsigned char *)"head", 4},
+ (PureSpan){owner.bytes, 5}, &owner, release);
+ CHECK(!pure_transfer_consume(&transfer, 5));
+ CHECK(transfer.active && !owner.releases);
+ CHECK(pure_transfer_consume(&transfer, 0));
+ unsigned char received[9];
+ size_t used = 0;
+ while (transfer.active) {
+ PureSpan span = pure_transfer_next(&transfer, 2);
+ CHECK(span.size && span.size <= 2);
+ memcpy(received + used, span.data, span.size);
+ used += span.size;
+ CHECK(pure_transfer_consume(&transfer, span.size));
+ CHECK((used == 9) == (owner.releases == 1));
+ }
+ CHECK(used == 9 && !memcmp(received, "heada\0bcd", 9));
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 1 && !pure_transfer_consume(&transfer, 0));
+ owner.bytes = malloc(3);
+ CHECK(owner.bytes);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){owner.bytes, 3}, &owner, release);
+ CHECK(pure_transfer_consume(&transfer, 1));
+ pure_transfer_abort(&transfer);
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 2 && !transfer.active);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){0}, &owner, release);
+ CHECK(owner.releases == 3 && !transfer.active);
+}
+
+static void storage(const char *path) {
+ CHECK(pure_store_init(path) == PURE_OK);
+ PureStoredView first, second;
+ CHECK(pure_store_get(path, "missing", 100, &first) == PURE_NOT_FOUND);
+ CHECK(!first.mapping && !first.mapped_size);
+ static const unsigned char original[] = {0, 1, 2, 255, 17};
+ static const unsigned char updated[] = {9, 8, 7};
+ int64_t revision;
+ CHECK(pure_store_put(path, "work", 0, (PureSpan){original, sizeof(original)}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ CHECK(pure_store_get(path, "work", sizeof(original) - 1, &first) == PURE_BUDGET);
+ CHECK(!first.mapping && !first.mapped_size);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 3, &first) == PURE_OK);
+ CHECK(first.object_size == sizeof(original) && first.body.size == 3 && !memcmp(first.body.data, original + 1, 3));
+ pure_store_release(&first);
+ CHECK(pure_store_get_range(path, "work", SIZE_MAX, 1, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, SIZE_MAX, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 2, &first) == PURE_BUDGET);
+ CHECK(pure_store_get_range(path, "work", sizeof(original), 0, 0, &first) == PURE_OK);
+ CHECK(!first.mapped_size && !first.body.size);
+ pure_store_release(&first);
+ CHECK(pure_store_get(path, "work", sizeof(original), &first) == PURE_OK);
+ CHECK(first.body.size == sizeof(original) && first.revision == 1);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 2);
+ CHECK(!memcmp(first.body.data, original, sizeof(original)));
+ CHECK(pure_store_get(path, "work", 100, &second) == PURE_OK);
+ CHECK(second.revision == 2 && second.body.size == sizeof(updated));
+ CHECK(!memcmp(second.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ pure_store_release(&first);
+ pure_store_release(&second);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){original, sizeof(original)}, &revision) == PURE_CONFLICT);
+ CHECK(revision == 2);
+
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 2 && !memcmp(first.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == 3);
+ failed_stage = -1;
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_CONFLICT);
+
+ /* A crashed unpublished writer leaves only a private file. A new publisher
+ * must still use the previous committed version, never an incomplete body. */
+ pid_t child = fork();
+ CHECK(child >= 0);
+ if (!child) {
+ failed_stage = PURE_AFTER_HEADER;
+ crash_at_stage = true;
+ pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision);
+ _exit(78);
+ }
+ int status;
+ CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 77);
+ CHECK(pure_store_init(path) == PURE_OK);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 4);
+
+ char file[320];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ CHECK(fd >= 0);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_put(path, "work", INT64_MAX, (PureSpan){original, sizeof(original)}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_put(path, "empty", 0, (PureSpan){0}, &revision) == PURE_OK);
+ CHECK(pure_store_get(path, "empty", 0, &first) == PURE_OK && first.body.size == 0);
+ pure_store_release(&first);
+
+ /* Range mapping crosses page boundaries without copying a whole object. */
+ long page = sysconf(_SC_PAGESIZE);
+ CHECK(page >= 128 && (size_t)page <= PURE_OBJECT_LIMIT / 3);
+ size_t size = (size_t)page * 3, offset = (size_t)page + 13, length = (size_t)page + 105;
+ unsigned char *bytes = malloc(size);
+ CHECK(bytes);
+ for (size_t i = 0; i < size; ++i) bytes[i] = (unsigned char)((i * 17u) ^ (i >> 8) ^ (i >> 16));
+ CHECK(pure_store_put(path, "range", 0, (PureSpan){bytes, size}, &revision) == PURE_OK);
+ CHECK(pure_store_get_range(path, "range", offset, length, length, &first) == PURE_OK);
+ CHECK(first.body.size == length && !memcmp(first.body.data, bytes + offset, length));
+ pure_store_release(&first);
+ free(bytes);
+ snprintf(file, sizeof(file), "%s/obj-broken", path);
+ fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0600);
+ CHECK(fd >= 0 && write(fd, "incomplete", 10) == 10 && close(fd) == 0);
+ CHECK(pure_store_get(path, "broken", 100, &first) == PURE_STORE_ERROR && !first.mapped_size);
+ CHECK(pure_store_put(path, "broken", 0, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_init(file) == PURE_STORE_ERROR);
+ struct stat info;
+ CHECK(stat(file, &info) == 0 && info.st_size == 10);
+}
+
+int main(void) {
+ transfers();
+ char directory[] = "/tmp/pure-connection-unit-XXXXXX";
+ CHECK(mkdtemp(directory));
+ char path[256];
+ snprintf(path, sizeof(path), "%s/store", directory);
+ storage(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ CHECK(rmdir(directory) == 0);
+ puts("{\"transfer\":\"partial-consumption-and-single-release\","
+ "\"storage\":\"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty\"}");
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-program.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-program.c
new file mode 100644
index 0000000..6a4a19d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-program.c
@@ -0,0 +1,111 @@
+#include "program.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static PureProgram parse(const char *source) {
+ PureProgram program;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &program, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return program;
+}
+static void invalid(const char *source) {
+ PureProgram program;
+ memset(&program, 0x5a, sizeof(program));
+ unsigned char original[sizeof(program)];
+ memcpy(original, &program, sizeof(program));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &program, error, sizeof(error)));
+ CHECK(*error && !memcmp(original, &program, sizeof(program)));
+}
+int main(void) {
+ char source[4096];
+ snprintf(source, sizeof(source), "%s %s", get, put);
+ PureProgram plan = parse(source);
+ CHECK(plan.read.to_end && plan.write.to_end && !plan.reply_input);
+ CHECK(!plan.view_definitions && !plan.read_required && !plan.input_required);
+ snprintf(source, sizeof(source), "%s on put { let a = range(request.body, 2, 10); "
+ "let b = range(a, 3, 4); let alias = b; "
+ "let saved = store.write(request.key, request.revision, alias); reply(saved, b); }", get);
+ plan = parse(source);
+ CHECK(plan.write.offset == 5 && plan.write.length == 4 && !plan.write.to_end);
+ CHECK(plan.reply.offset == 5 && plan.reply.length == 4 && plan.reply_input);
+ CHECK(plan.input_required == 12 && plan.range_definitions == 2 && plan.view_definitions == 3);
+ /* Ordered reference views keep even unused bounds failures observable. */
+ unsigned char bytes[160];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 7);
+ size_t comparisons = 0;
+ for (size_t a = 0; a < 4; ++a) for (size_t b = 0; b < 6; ++b)
+ for (size_t c = 0; c <= b; ++c) for (size_t d = 0; d <= b - c; ++d) {
+ size_t unused_end = (a + b + c) % 12;
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); "
+ "let unused = range(o.body, %zu, 0); let first = range(o.body, %zu, %zu); "
+ "let second = range(first, %zu, %zu); reply(o, second); } %s",
+ unused_end, a, b, c, d, put);
+ plan = parse(source);
+ for (size_t n = 0; n < 16; ++n) {
+ bool reference_ok = unused_end <= n && a <= n && b <= n - a;
+ PureSpan selected;
+ bool prepared_ok = n >= plan.read_required &&
+ pure_region_span(plan.read, (PureSpan){bytes, n}, &selected);
+ CHECK(reference_ok == prepared_ok);
+ if (reference_ok) {
+ CHECK(selected.size == d);
+ CHECK(!d || !memcmp(selected.data, bytes + a + c, d));
+ }
+ ++comparisons;
+ }
+ }
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); reply(o); } %s", put);
+ plan = parse(source);
+ CHECK(!plan.read.to_end && !plan.read.length);
+ const char *bad_get[] = {
+ "on get { let o = store.read(request.key); let x = range(o.body, 0, 2); let y = range(x, 2, 1); reply(o, y); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 184467440737095516160, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 1449984, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let o = o.body; reply(o); }",
+ "on get { let o = store.read(request.key); let x = x; reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = store.read(request.key); reply(x); }",
+ "on get { let o = store.read(request.key); reply(o, request.body); }",
+ "on get { let o = store.read(request.key); let x = o.body; reply(x); }",
+ "on get { let o = store.read(request.key); reply(o.body); }",
+ "on get { let o = store.read(request.key); reply(o); let x = o.body; }",
+ "on get { let o = store.read(request.key); reply(o);", "on get {}"
+ };
+ for (size_t i = 0; i < sizeof(bad_get) / sizeof(*bad_get); ++i) {
+ snprintf(source, sizeof(source), "%s %s", bad_get[i], put); invalid(source);
+ }
+ const char *bad_put[] = {
+ "on put { let s = store.write(request.key, request.revision, request.body); let b = range(request.body, 0, 1); reply(s, b); }",
+ "on put { let s = store.write(request.key, request.revision, request.body); reply(s, s.body); }",
+ "on put { let s = store.read(request.key); reply(s); }"
+ };
+ for (size_t i = 0; i < sizeof(bad_put) / sizeof(*bad_put); ++i) {
+ snprintf(source, sizeof(source), "%s %s", get, bad_put[i]); invalid(source);
+ }
+ invalid(get);
+ snprintf(source, sizeof(source), "%s %s %s", get, get, put); invalid(source);
+ snprintf(source, sizeof(source), "%s %s garbage", get, put); invalid(source);
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); ");
+ for (size_t i = 0; i < 32; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let x%zu = o.body; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "reply(o); } %s", put); invalid(source);
+ char oversized[PURE_PROGRAM_LIMIT + 1];
+ memset(oversized, ' ', sizeof(oversized));
+ char error[160];
+ CHECK(!pure_program_parse(oversized, sizeof(oversized), &plan, error, sizeof(error)));
+ const char embedded[] = "on get\0{}";
+ CHECK(!pure_program_parse(embedded, sizeof(embedded) - 1, &plan, error, sizeof(error)));
+ PureSpan selected;
+ CHECK(pure_region_span((PureRegion){0}, (PureSpan){0}, &selected) && !selected.data && !selected.size);
+ printf("{\"program\":\"prepare-views-preserve-guards-types-effects-and-atomic-install\","
+ "\"boundary_semantic_comparisons\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-runtime.c b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-runtime.c
new file mode 100644
index 0000000..7ce2290
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/connections/test-runtime.c
@@ -0,0 +1,285 @@
+#define _POSIX_C_SOURCE 200809L
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const PureProgram identity = {
+ .read = {.to_end = true}, .write = {.to_end = true},
+ .reply = {.to_end = true}, .reply_input = true
+};
+typedef struct {
+ size_t allocations, writes, frees, live;
+ bool allocation_failure, oversized_read, reenter;
+ PureRuntime *runtime;
+ unsigned char received[256];
+ size_t received_size;
+} Host;
+typedef struct { Host *host; unsigned char bytes[]; } Allocation;
+
+static void free_input(void *pointer, size_t size) {
+ Allocation *a = pointer;
+ assert(size > 0 && a->host->live > 0);
+ ++a->host->frees;
+ --a->host->live;
+ free(a);
+}
+
+static bool allocate(void *context, size_t size, PureResource *out) {
+ Host *host = context;
+ if (host->allocation_failure) return false;
+ Allocation *a = malloc(sizeof(*a) + size);
+ assert(a);
+ a->host = host;
+ ++host->allocations;
+ ++host->live;
+ *out = (PureResource){.body = {a->bytes, size}, .allocation = a,
+ .allocation_size = size, .release = free_input};
+ return true;
+}
+
+static PureResult write_value(void *context, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ Host *host = context;
+ (void)key;
+ if (host->reenter) {
+ PureTicket ignored;
+ assert(pure_runtime_accept(host->runtime, PURE_INPUT_WRITE, "reenter", 0, 0, &ignored) == PURE_INVALID);
+ assert(!pure_runtime_step(host->runtime));
+ }
+ if (expected == 99) { *revision = 1; return PURE_CONFLICT; }
+ ++host->writes;
+ assert(body.size <= sizeof(host->received));
+ if (body.size) memcpy(host->received, body.data, body.size);
+ host->received_size = body.size;
+ *revision = 1;
+ return PURE_OK;
+}
+
+static PureResult read_value(void *context, const char *key, PureRegion range,
+ size_t minimum, size_t available, PureResource *out, int64_t *revision) {
+ Host *host = context;
+ (void)key; (void)range; (void)minimum;
+ if (!host->oversized_read) return PURE_NOT_FOUND;
+ assert(available < 1000);
+ assert(allocate(host, available + 1, out));
+ *revision = 1;
+ return PURE_OK; /* Deliberately violates the available-credit contract. */
+}
+
+static PureHost port(Host *host) {
+ return (PureHost){host, allocate, read_value, write_value};
+}
+
+static PureTicket submit(PureRuntime *r, const char *key, const void *bytes, size_t length) {
+ PureTicket ticket;
+ assert(pure_runtime_accept(r, PURE_INPUT_WRITE, key, 0, length, &ticket) == PURE_OK);
+ size_t capacity;
+ unsigned char *input = pure_runtime_ingress(ticket, &capacity);
+ assert(capacity == length);
+ if (length) memcpy(input, bytes, length);
+ assert(pure_runtime_ready(ticket));
+ assert(!pure_runtime_ready(ticket));
+ return ticket;
+}
+
+static PureOutcome completed(PureRuntime *r, PureTicket ticket) {
+ PureOutcome result;
+ while (!pure_runtime_result(ticket, &result)) assert(pure_runtime_step(r));
+ return result;
+}
+
+static void admission_and_lifecycle(void) {
+ Host host = {0};
+ PureRuntime r;
+ PureWork work[3];
+ assert(pure_runtime_init(&r, work, 3, &identity, port(&host), 5));
+ host.runtime = &r;
+ PureTicket a, untouched = {0}, out = untouched;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "../bad", 0, 1, &out) == PURE_INVALID);
+ assert(!out.runtime && !host.allocations);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "a", 0, 4, &a) == PURE_OK);
+ assert(r.retained == 4 && !pure_runtime_step(&r) && !host.writes);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "b", 0, 2, &out) == PURE_BUDGET);
+ assert(!out.runtime && host.allocations == 1);
+ assert(pure_runtime_cancel(a));
+ PureOutcome cancelled;
+ assert(pure_runtime_result(a, &cancelled) && cancelled.status == PURE_CANCELLED);
+ assert(r.retained == 0 && host.frees == 1 && !pure_runtime_cancel(a));
+ assert(pure_runtime_release(a) && !pure_runtime_release(a));
+ assert(!pure_runtime_result(a, &cancelled));
+
+ PureTicket first = submit(&r, "first", "1", 1);
+ PureTicket middle = submit(&r, "middle", "2", 1);
+ PureTicket last = submit(&r, "last", "3", 1);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "full", 0, 0, &out) == PURE_BUSY);
+ assert(pure_runtime_cancel(middle));
+ assert(pure_runtime_release(middle));
+ pure_runtime_stop(&r);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "closed", 0, 0, &out) == PURE_CLOSED);
+ assert(!pure_runtime_restart(&r, &identity, port(&host), 5));
+ host.reenter = true;
+ assert(completed(&r, first).status == PURE_OK && host.received[0] == '1');
+ assert(completed(&r, last).status == PURE_OK && host.received[0] == '3');
+ assert(!pure_runtime_step(&r));
+ assert(pure_runtime_release(first) && pure_runtime_release(last));
+ assert(r.active == 0 && r.retained == 0 && host.live == 0);
+ assert(pure_runtime_restart(&r, &identity, port(&host), 5));
+ PureTicket next = submit(&r, "next", "4", 1);
+ assert(next.generation > last.generation && !pure_runtime_ready(a));
+ assert(!pure_runtime_release(last));
+ assert(pure_runtime_release(next)); /* queued input: no effect */
+ assert(host.writes == 2 && !pure_runtime_step(&r));
+
+ host.allocation_failure = true;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "no_memory", 0, 1, &out) == PURE_ALLOCATION);
+ assert(r.active == 0 && r.retained == 0);
+ host.allocation_failure = false;
+ PureHost denied = port(&host);
+ denied.write = NULL;
+ assert(pure_runtime_restart(&r, &identity, denied, 5));
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "denied", 0, 1, &out) == PURE_DENIED);
+ assert(pure_runtime_restart(&r, &identity, port(&host), 5));
+ host.oversized_read = true;
+ assert(pure_runtime_accept(&r, PURE_INPUT_READ, "bad_host", 0, 0, &out) == PURE_OK);
+ assert(completed(&r, out).status == PURE_BUDGET && host.live == 0 && r.retained == 0);
+ assert(pure_runtime_release(out));
+ r.serial = UINT64_MAX;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "exhausted", 0, 0, &out) == PURE_LIMIT);
+}
+
+static void forwarding(void) {
+ Host a = {0}, b = {0}, c = {0};
+ PureRuntime source, left, right;
+ PureWork source_work[1], left_work[1], right_work[1];
+ assert(pure_runtime_init(&source, source_work, 1, &identity, port(&a), 8));
+ assert(pure_runtime_init(&left, left_work, 1, &identity, port(&b), 2));
+ assert(pure_runtime_init(&right, right_work, 1, &identity, port(&c), 8));
+ PureTicket original = submit(&source, "original", "value", 5), x = {0}, y;
+ PureOutcome result = completed(&source, original);
+ assert(result.status == PURE_OK);
+ const unsigned char *backing = result.body.data;
+ assert(pure_runtime_forward(original, &left, "left", 0, &x) == PURE_BUDGET);
+ assert(!x.runtime && source.work[0].pins == 0);
+ assert(pure_runtime_restart(&left, &identity, port(&b), 8));
+ assert(pure_runtime_forward(original, &left, "left", 0, &x) == PURE_OK);
+ assert(pure_runtime_forward(original, &right, "right", 0, &y) == PURE_OK);
+ assert(pure_runtime_release(original));
+ assert(!pure_runtime_result(original, &result));
+ pure_runtime_stop(&source);
+ assert(!pure_runtime_restart(&source, &identity, port(&a), 8));
+ assert(a.live == 1 && !b.allocations && !c.allocations);
+ assert(pure_runtime_cancel(x) && pure_runtime_release(x));
+ assert(a.live == 1 && !b.writes);
+ result = completed(&right, y);
+ assert(result.body.data == backing && result.body.size == 5 && !memcmp(result.body.data, "value", 5));
+ assert(c.writes == 1 && !c.allocations && source.retained == 5);
+ assert(!pure_runtime_cancel(y)); /* effects cannot be rolled back */
+ assert(pure_runtime_release(y));
+ assert(a.frees == 1 && !source.active && !source.retained && !right.active && !right.retained);
+ assert(pure_runtime_restart(&source, &identity, port(&a), 8));
+
+ /* A completed consumer does not retain its input when the program has no
+ * input-backed reply. The producing domain can then be reclaimed early. */
+ PureProgram no_reply = identity;
+ no_reply.reply_input = false;
+ assert(pure_runtime_restart(&right, &no_reply, port(&c), 8));
+ original = submit(&source, "again", "last", 4);
+ assert(completed(&source, original).status == PURE_OK);
+ assert(pure_runtime_forward(original, &right, "no_reply", 0, &y) == PURE_OK);
+ assert(pure_runtime_release(original));
+ assert(completed(&right, y).body.size == 0 && a.live == 0);
+ assert(source.active == 0 && right.active == 1 && right.retained == 0);
+ assert(pure_runtime_release(y));
+}
+
+static void long_chain(void) {
+ enum { COUNT = 1024 };
+ PureWork *work = calloc(COUNT, sizeof(*work));
+ assert(work);
+ Host host = {0};
+ PureRuntime r;
+ assert(pure_runtime_init(&r, work, COUNT, &identity, port(&host), COUNT));
+ PureTicket ticket = submit(&r, "chain", "x", 1);
+ for (size_t i = 1; i < COUNT; ++i) {
+ assert(completed(&r, ticket).status == PURE_OK);
+ PureTicket next;
+ assert(pure_runtime_forward(ticket, &r, "chain", 0, &next) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ ticket = next;
+ }
+ assert(completed(&r, ticket).status == PURE_OK);
+ assert(host.allocations == 1 && r.active == COUNT);
+ assert(pure_runtime_release(ticket));
+ assert(r.retained == 0 && r.active == 0 && host.frees == 1);
+ free(work);
+}
+
+static void actual_storage(void) {
+ char directory[] = "/tmp/pure-runtime-check-XXXXXX";
+ assert(mkdtemp(directory));
+ char source_path[128], target_path[128], name[160];
+ snprintf(source_path, sizeof(source_path), "%s/source", directory);
+ snprintf(target_path, sizeof(target_path), "%s/target", directory);
+ assert(pure_store_init(source_path) == PURE_OK && pure_store_init(target_path) == PURE_OK);
+ PureProgram selection;
+ char error[160];
+ assert(pure_program_load("examples/selection.pure", &selection, error, sizeof(error)));
+ PureRuntime source, target;
+ PureWork a[2], b[2];
+ assert(pure_runtime_init(&source, a, 2, &selection, pure_store_host(source_path), 128));
+ assert(pure_runtime_init(&target, b, 2, &identity, pure_store_host(target_path), 128));
+ const unsigned char bytes[] = {1,0,0,0, 3,0,0,0, 'a','b','c','d','e'};
+ PureTicket ticket = submit(&source, "excerpt", bytes, sizeof(bytes)), consumer;
+ PureOutcome result = completed(&source, ticket);
+ assert(result.status == PURE_OK && result.body.size == 3 && !memcmp(result.body.data, "bcd", 3));
+ assert(pure_runtime_forward(ticket, &target, "archive", 0, &consumer) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ assert(source.active == 1 && source.retained == sizeof(bytes));
+ assert(completed(&target, consumer).status == PURE_OK);
+ assert(pure_runtime_release(consumer) && source.active == 0);
+ PureStoredView stored = {0};
+ assert(pure_store_get(target_path, "archive", 128, &stored) == PURE_OK);
+ assert(stored.body.size == 3 && !memcmp(stored.body.data, "bcd", 3));
+ pure_store_release(&stored);
+
+ assert(pure_runtime_accept(&source, PURE_INPUT_READ, "excerpt", 0, 0, &ticket) == PURE_OK);
+ assert(completed(&source, ticket).status == PURE_OK);
+ assert(pure_runtime_forward(ticket, &target, "snapshot", 0, &consumer) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ int64_t revision;
+ assert(pure_store_put(source_path, "excerpt", 1, (PureSpan){(const unsigned char *)"new", 3}, &revision) == PURE_OK);
+ result = completed(&target, consumer);
+ assert(result.body.size == 3 && !memcmp(result.body.data, "bcd", 3));
+ assert(pure_runtime_release(consumer));
+
+ unsigned char invalid[] = {255,255,255,255, 1,0,0,0, 'x'};
+ ticket = submit(&source, "invalid", invalid, sizeof(invalid));
+ assert(completed(&source, ticket).status == PURE_LIMIT);
+ assert(pure_runtime_release(ticket));
+ assert(pure_store_get(source_path, "invalid", 128, &stored) == PURE_NOT_FOUND);
+ assert(source.active == 0 && target.active == 0 && source.retained == 0 && target.retained == 0);
+ const char *files[] = {"source/obj-excerpt", "source/.writer.lock", "target/obj-archive",
+ "target/obj-snapshot", "target/.writer.lock"};
+ for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); ++i) {
+ snprintf(name, sizeof(name), "%s/%s", directory, files[i]);
+ assert(unlink(name) == 0);
+ }
+ assert(rmdir(source_path) == 0 && rmdir(target_path) == 0 && rmdir(directory) == 0);
+}
+
+int main(void) {
+ admission_and_lifecycle();
+ forwarding();
+ long_chain();
+ actual_storage();
+ printf("{\"runtime_tests\":\"passed\",\"domain_bytes\":%zu,\"work_slot_bytes\":%zu,"
+ "\"ticket_bytes\":%zu,\"prepared_program_bytes\":%zu,\"forwarding_chain\":1024,"
+ "\"native_storage_pipeline\":true}\n", sizeof(PureRuntime), sizeof(PureWork),
+ sizeof(PureTicket), sizeof(PureProgram));
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/cli.mjs b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/cli.mjs
new file mode 100644
index 0000000..b67f4d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/cli.mjs
@@ -0,0 +1,127 @@
+#!/usr/bin/env node
+import { readFile, writeFile } from 'node:fs/promises';
+import { createInterface } from 'node:readline';
+import { createRuntime } from './web/runtime.mjs';
+import { parseProject } from './web/project.mjs';
+import { remoteTarget, pushProject, pullProject } from './remote.mjs';
+
+const help = `Pure authoring workbench · 같은 정의와 Zig 실행기
+ load PATH .pure 파일을 적용 (같은 이름의 상태 보존)
+ down NAME 정의한 입력 누르기
+ up NAME 정의한 입력 놓기
+ point NAME PHASE X Y 좌표 입력 (down / move / up / cancel)
+ point-target NAME VIEW PHASE X Y 그룹의 대상에 좌표 입력
+ change NAME VALUE 숫자 입력 전달
+ frame [1..600] 시간 진행, 1프레임 = 1/60초
+ show 상태와 도형 출력
+ limits C H W 표시 캐시(0..32)·변경 기록(0..8)·작업량(0..4294967295) 설정
+ forget [PART] 표시 기록 삭제: all, values, history (상태는 유지)
+ costs 마지막 표시 계산의 작업량·명령 수·캐시 적중 출력
+ reset 현재 정의의 초기 상태로
+ save PATH 적용한 정의를 저장
+ save-project PATH 적용 코드와 현재 배치를 JSON으로 저장
+ restore PATH 저장한 배치를 복원 (초안이 있으면 파일에 보존)
+ connect URL KEY 로컬 네이티브 저장 서버의 작업물에 연결
+ push [REVISION] 현재 배치를 저장 (첫 생성은 push 0, 충돌 시 기존 값 유지)
+ pull 원격 배치를 검증·복원하고 revision 기억
+ help / quit
+브라우저와 별도 인스턴스입니다. 임의 JavaScript는 실행하지 않습니다.`;
+
+async function main() {
+ const args = process.argv.slice(2);
+ if (args.includes('--help')) { console.log(help); return; }
+ if (args.length > 1) throw new Error('사용법: node cli.mjs [project.pure]');
+ const runtime = await createRuntime(await readFile(new URL('./web/core.wasm', import.meta.url)));
+ let savedDraft = null;
+ let remote = null, remoteRevision = null;
+ async function loadFile(path, restoreOnly = false) {
+ const content = await readFile(path, 'utf8');
+ if (restoreOnly || path.toLowerCase().endsWith('.json')) {
+ const project = parseProject(content);
+ if (project.version === 2) {
+ savedDraft = runtime.restoreDocument(project).draft;
+ return;
+ }
+ if (restoreOnly) throw new Error('현재 배치가 포함된 version 2 파일이 필요합니다.');
+ runtime.apply(project.source);
+ } else runtime.apply(content);
+ savedDraft = null;
+ }
+ if (args[0]) await loadFile(args[0]); else runtime.apply('');
+ const terminal = createInterface({ input: process.stdin, output: process.stdout, terminal: Boolean(process.stdin.isTTY) });
+ if (process.stdin.isTTY) console.log(help);
+ terminal.setPrompt('pure> ');
+ if (process.stdin.isTTY) terminal.prompt();
+ for await (const line of terminal) {
+ try {
+ const match = /^(\S+)(?:\s+(.+))?$/.exec(line.trim());
+ const name = match?.[1] || 'show';
+ const arg = match?.[2];
+ if (name === 'quit') { terminal.close(); break; }
+ if (name === 'help') console.log(help);
+ else if (name === 'costs' && !arg) console.log(JSON.stringify({ evaluation: runtime.evaluationStats() }));
+ else {
+ if (name === 'load' && arg) await loadFile(arg);
+ else if (name === 'restore' && arg) await loadFile(arg, true);
+ else if (name === 'connect' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('connect URL KEY 형식을 사용하세요.');
+ remote = remoteTarget(parts[0], parts[1]);
+ remoteRevision = null;
+ console.log(JSON.stringify({ remote: remote.href }));
+ } else if (name === 'push') {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const expected = arg ?? remoteRevision;
+ if (expected === null) throw new Error('먼저 pull로 버전을 읽거나 push 0으로 새 작업물을 만드세요.');
+ remoteRevision = await pushProject(remote, expected, runtime.exportDocument(savedDraft ?? undefined));
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, stored: true }));
+ } else if (name === 'pull' && !arg) {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const loaded = await pullProject(remote);
+ savedDraft = runtime.restoreDocument(loaded.project).draft;
+ remoteRevision = loaded.revision;
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, restored: true }));
+ }
+ else if (name === 'save-project' && arg) await writeFile(arg, JSON.stringify(runtime.exportDocument(savedDraft ?? undefined), null, 2) + '\n', {flag:'wx'});
+ else if (name === 'save' && arg) await writeFile(arg, runtime.exportProject().source, { flag: 'wx' });
+ else if (name === 'down' && arg) runtime.down(arg, 'terminal');
+ else if (name === 'up' && arg) runtime.up(arg, 'terminal');
+ else if (name === 'point' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 4) throw new Error('point NAME PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[1], Number(parts[2]), Number(parts[3]), 'terminal');
+ } else if (name === 'point-target' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 5) throw new Error('point-target NAME VIEW PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[2], Number(parts[3]), Number(parts[4]), 'terminal', parts[1]);
+ } else if (name === 'change' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('change NAME VALUE 형식을 사용하세요.');
+ runtime.change(parts[0], Number(parts[1]), 'terminal');
+ } else if (name === 'frame') {
+ if (arg !== undefined && !/^\d+$/.test(arg)) throw new Error('frame 1..600 정수를 입력하세요.');
+ const count = arg === undefined ? 1 : Number(arg);
+ if (count < 1 || count > 600) throw new Error('frame 1..600 정수를 입력하세요.');
+ runtime.frame(count);
+ } else if (name === 'reset' && !arg) runtime.reset();
+ else if (name === 'limits' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 3 || parts.some(part => !/^\d+$/.test(part)))
+ throw new Error('limits C H W 정수 세 개를 입력하세요.');
+ const [cacheEntries, historyEntries, workLimit] = parts.map(Number);
+ runtime.configureEvaluation({ cacheEntries, historyEntries, workLimit });
+ } else if (name === 'forget') runtime.forgetEvaluation(arg || 'all');
+ else if (name !== 'show' || arg) throw new Error('명령 형식을 확인하세요. help로 안내를 볼 수 있습니다.');
+ const result = runtime.snapshot();
+ console.log(JSON.stringify(result));
+ if (result.lastError && !process.stdin.isTTY) process.exitCode = 1;
+ }
+ } catch (error) {
+ console.error(`${error.line ? `${error.line}:${error.column || 1} ` : ''}${error.message}`);
+ if (!process.stdin.isTTY) process.exitCode = 1;
+ }
+ if (process.stdin.isTTY) terminal.prompt();
+ }
+}
+
+main().catch((error) => { console.error(error.message); process.exitCode = 1; });
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/examples/direct.pure b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/examples/direct.pure
new file mode 100644
index 0000000..b29721c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/examples/direct.pure
@@ -0,0 +1,47 @@
+# 도형을 잡은 위치를 유지해 이동합니다. 취소하면 잡기 전 위치로 돌아갑니다.
+state x = 80
+state y = 160
+state grab_x = 0
+state grab_y = 0
+state start_x = 80
+state start_y = 160
+state dragging = 0
+
+input drag = pointer(tile)
+input left = ArrowLeft
+input right = ArrowRight
+
+box left_area(20, 100, 280, 220, "#233a31")
+box right_area(340, 100, 280, 220, "#343b25")
+box tile(x, y, 56, 44, "#c9f08b")
+text horizontal(30, 45, x, "x: ")
+text vertical(180, 45, y, "y: ")
+text region(350, 70, x >= 320, "오른쪽 영역: ")
+text active(30, 75, dragging, "잡고 있음: ")
+
+on drag.down {
+ start_x = x
+ start_y = y
+ grab_x = event_x - x
+ grab_y = event_y - y
+ dragging = 1
+}
+on drag.move {
+ x = clamp(event_x - grab_x, 20, 564)
+ y = clamp(event_y - grab_y, 100, 276)
+}
+on drag.up {
+ # 놓기는 마지막으로 표시한 위치를 확정합니다.
+ dragging = 0
+}
+on drag.cancel {
+ x = start_x
+ y = start_y
+ dragging = 0
+}
+on left.down {
+ if dragging == 0 { x = max(20, x - 10) }
+}
+on right.down {
+ if dragging == 0 { x = min(564, x + 10) }
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/remote.mjs b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/remote.mjs
new file mode 100644
index 0000000..6ee6a59
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/remote.mjs
@@ -0,0 +1,89 @@
+import http from 'node:http';
+import { MAX_PROJECT_BYTES, parseProject } from './web/project.mjs';
+
+const maxRevision = 9223372036854775807n;
+function revisionText(value, allowZero = false) {
+ if (typeof value !== 'string' || !/^(0|[1-9]\d*)$/.test(value) ||
+ value.length > 19 || BigInt(value) > maxRevision || (!allowZero && value === '0'))
+ throw new Error('revision은 범위 안의 정수 문자열이어야 합니다.');
+ return value;
+}
+
+export function remoteTarget(base, key) {
+ const url = new URL(base);
+ if (url.protocol !== 'http:' || !['127.0.0.1', 'localhost'].includes(url.hostname) ||
+ url.username || url.password || url.pathname !== '/' || url.search || url.hash)
+ throw new Error('현재 연결 호스트는 로컬 http://127.0.0.1:PORT 형식을 사용합니다.');
+ if (!/^[A-Za-z0-9_-]{1,64}$/.test(key)) throw new Error('작업물 이름은 영문·숫자·_·- 1~64자입니다.');
+ url.hostname = '127.0.0.1';
+ url.pathname = `/objects/${key}`;
+ return url;
+}
+
+function request(url, method, body, headers = {}) {
+ return new Promise((resolve, reject) => {
+ let done = false;
+ const finish = (error, value) => {
+ if (done) return;
+ done = true;
+ clearTimeout(deadline);
+ if (error) reject(error); else resolve(value);
+ };
+ const req = http.request(url, { method, agent: false, headers: { ...headers,
+ 'Content-Length': body?.byteLength ?? 0, Connection: 'close' } }, (res) => {
+ const chunks = [];
+ let size = 0;
+ res.on('data', (chunk) => {
+ size += chunk.length;
+ if (size > MAX_PROJECT_BYTES) {
+ const error = new Error('서버 작업물이 허용 크기를 넘었습니다.');
+ finish(error);
+ res.destroy(error);
+ req.destroy(error);
+ } else chunks.push(chunk);
+ });
+ res.on('error', (error) => finish(error));
+ res.on('aborted', () => finish(new Error('응답이 완료되기 전에 연결이 끊겼습니다.')));
+ res.on('end', () => {
+ if (res.statusCode !== 200) {
+ const error = new Error(`원격 작업 실패: ${res.statusCode} ${res.headers['x-pure-error'] ?? ''}`.trim());
+ error.status = res.statusCode;
+ error.etag = res.headers.etag;
+ finish(error);
+ return;
+ }
+ try {
+ const match = /^"([1-9]\d*)"$/.exec(res.headers.etag ?? '');
+ if (!match) throw new Error('서버의 revision 응답이 올바르지 않습니다.');
+ const revision = revisionText(match[1]);
+ finish(null, { revision, bytes: Buffer.concat(chunks, size) });
+ } catch (error) { finish(error); }
+ });
+ });
+ const deadline = setTimeout(() => {
+ const error = new Error('원격 작업 시간 초과: 저장 완료 여부는 다시 확인해야 합니다.');
+ finish(error);
+ req.destroy(error);
+ }, 12000);
+ req.on('error', (error) => finish(error));
+ req.end(body);
+ });
+}
+
+export async function pushProject(target, expected, project) {
+ revisionText(expected, true);
+ const text = JSON.stringify(project);
+ parseProject(text);
+ const body = Buffer.from(text, 'utf8');
+ const headers = expected === '0' ? { 'If-None-Match': '*' } : { 'If-Match': `"${expected}"` };
+ const result = await request(target, 'PUT', body, headers);
+ return result.revision;
+}
+
+export async function pullProject(target) {
+ const result = await request(target, 'GET');
+ const text = new TextDecoder('utf-8', { fatal: true }).decode(result.bytes);
+ const project = parseProject(text);
+ if (project.version !== 2) throw new Error('현재 배치를 포함한 version 2 작업물이 필요합니다.');
+ return { project, revision: result.revision };
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/compiler.mjs b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/compiler.mjs
new file mode 100644
index 0000000..6aec335
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/compiler.mjs
@@ -0,0 +1,496 @@
+// Pure's experimental scalar interaction language. No host code is evaluated.
+const LIMITS = Object.freeze({ sourceBytes: 32768, states: 32, inputs: 8,
+ views: 24, handlers: 64, instructions: 512, depth: 64, stack: 64 });
+const RESERVED = new Set(['frame', 'dt', 'event_x', 'event_y', 'event_value', 'min', 'max', 'clamp']);
+const BINARY = new Map([
+ ['||', [1, 15]], ['&&', [2, 14]], ['==', [3, 12]], ['!=', [3, 13]],
+ ['<', [4, 8]], ['<=', [4, 9]], ['>', [4, 10]], ['>=', [4, 11]],
+ ['+', [5, 3]], ['-', [5, 4]], ['*', [6, 5]], ['/', [6, 6]],
+]);
+const FUNCTIONS = { min: [2, 17], max: [2, 18], clamp: [3, 19] };
+const VIEW_FIELDS = { box: ['x', 'y', 'width', 'height'],
+ circle: ['x', 'y', 'radius'], text: ['x', 'y', 'value'] };
+
+function fail(token, message) {
+ const error = new Error(`${message} (${token.line}:${token.column})`);
+ error.line = token.line;
+ error.column = token.column;
+ throw error;
+}
+
+function lex(source) {
+ const tokens = [];
+ let offset = 0, line = 1, column = 1;
+ const advance = () => {
+ const char = source[offset++];
+ if (char === '\n') { line++; column = 1; } else column++;
+ return char;
+ };
+ while (offset < source.length) {
+ const char = source[offset];
+ if (char === ' ' || char === '\t' || char === '\r') { advance(); continue; }
+ if (char === '#') { while (offset < source.length && source[offset] !== '\n') advance(); continue; }
+ const token = { line, column };
+ if (char === '\n') { advance(); tokens.push({ ...token, kind: 'nl' }); continue; }
+ if (char === '"') {
+ advance();
+ let value = '', closed = false;
+ while (offset < source.length) {
+ const next = advance();
+ if (next === '"') { closed = true; break; }
+ if (next === '\n' || next === '\r') fail(token, 'Strings must fit on one line');
+ if (next === '\\') {
+ const escaped = advance();
+ const escapes = { n: '\n', r: '\r', t: '\t', '"': '"', '\\': '\\' };
+ if (!Object.hasOwn(escapes, escaped)) fail(token, 'Unsupported string escape');
+ value += escapes[escaped];
+ } else value += next;
+ }
+ if (!closed) fail(token, 'Unterminated string');
+ tokens.push({ ...token, kind: 'string', value }); continue;
+ }
+ const remaining = source.slice(offset);
+ const number = remaining.match(/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/);
+ if (number) {
+ const value = Number(number[0]);
+ if (!Number.isFinite(value)) fail(token, 'Number must be finite');
+ for (let i = 0; i < number[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'number', value }); continue;
+ }
+ const name = remaining.match(/^[A-Za-z_][A-Za-z_0-9]*/);
+ if (name) {
+ for (let i = 0; i < name[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'name', value: name[0] }); continue;
+ }
+ const pair = source.slice(offset, offset + 2);
+ if (['<=', '>=', '==', '!=', '&&', '||'].includes(pair)) {
+ advance(); advance(); tokens.push({ ...token, kind: pair }); continue;
+ }
+ if ('=+-*/!<>(){},.;:'.includes(char)) {
+ advance(); tokens.push({ ...token, kind: char }); continue;
+ }
+ fail(token, `Unexpected character ${JSON.stringify(char)}`);
+ }
+ tokens.push({ kind: 'eof', line, column });
+ return tokens;
+}
+
+class Parser {
+ constructor(tokens) { this.tokens = tokens; this.position = 0; this.depth = 0; }
+ peek() { return this.tokens[this.position]; }
+ take() { return this.tokens[this.position++]; }
+ is(kind, value) { return this.peek().kind === kind && (value === undefined || this.peek().value === value); }
+ expect(kind, description = kind) {
+ if (!this.is(kind)) fail(this.peek(), `Expected ${description}`);
+ return this.take();
+ }
+ newlines() { while (this.is('nl')) this.take(); }
+ separators() { while (this.is('nl') || this.is(';')) this.take(); }
+ end() {
+ if (!['nl', ';', '}', 'eof'].includes(this.peek().kind)) fail(this.peek(), 'Expected newline or semicolon');
+ this.separators();
+ }
+ reference(token) {
+ if (!this.is('.')) return token.value;
+ this.take();
+ return `${token.value}.${this.expect('name', 'field name').value}`;
+ }
+ initial() {
+ let sign = 1;
+ if (this.is('-') || this.is('+')) sign = this.take().kind === '-' ? -1 : 1;
+ return sign * this.expect('number', 'numeric state initializer').value;
+ }
+ node(token, properties, children = []) {
+ const depth = 1 + Math.max(0, ...children.map(child => child.depth));
+ if (depth > LIMITS.depth) fail(token, 'Expression nesting exceeds 64');
+ return { token, depth, ...properties };
+ }
+ expression(minimum = 0, multiline = false) {
+ if (++this.depth > LIMITS.depth) fail(this.peek(), 'Expression nesting exceeds 64');
+ if (multiline) this.newlines();
+ const token = this.take();
+ let left;
+ if (token.kind === 'number') left = this.node(token, { kind: 'constant', value: token.value });
+ else if (token.kind === '-' || token.kind === '!') {
+ const child = this.expression(7, multiline);
+ left = this.node(token, { kind: 'unary', op: token.kind === '-' ? 7 : 16, child }, [child]);
+ } else if (token.kind === '(') {
+ left = this.expression(0, true); this.newlines(); this.expect(')');
+ } else if (token.kind === 'name') {
+ if (Object.hasOwn(FUNCTIONS, token.value) && this.is('(')) {
+ this.take();
+ const args = [];
+ this.newlines();
+ if (!this.is(')')) {
+ for (;;) {
+ args.push(this.expression(0, true)); this.newlines();
+ if (!this.is(',')) break;
+ this.take();
+ }
+ }
+ this.expect(')');
+ if (args.length !== FUNCTIONS[token.value][0]) fail(token, `${token.value} expects ${FUNCTIONS[token.value][0]} arguments`);
+ left = this.node(token, { kind: 'call', op: FUNCTIONS[token.value][1], args }, args);
+ } else left = this.node(token, { kind: 'reference', name: this.reference(token) });
+ } else fail(token, 'Expected a number, state, or expression');
+ for (;;) {
+ if (multiline) this.newlines();
+ const entry = BINARY.get(this.peek().kind);
+ if (!entry || entry[0] < minimum) break;
+ const operator = this.take();
+ const right = this.expression(entry[0] + 1, multiline);
+ left = this.node(operator, { kind: 'binary', op: entry[1], left, right }, [left, right]);
+ }
+ this.depth--;
+ return left;
+ }
+ block(depth = 0) {
+ if (depth >= LIMITS.depth) fail(this.peek(), 'Handler nesting exceeds 64');
+ this.newlines(); this.expect('{'); this.separators();
+ const statements = [];
+ while (!this.is('}')) {
+ const token = this.expect('name', 'assignment, if, or closing brace');
+ if (token.value === 'if' && !this.is('=')) {
+ const condition = this.expression();
+ const body = this.block(depth + 1);
+ statements.push({ kind: 'if', token, condition, body });
+ } else {
+ const name = this.reference(token);
+ this.expect('=');
+ statements.push({ kind: 'assign', token, name, expression: this.expression() });
+ }
+ this.end();
+ }
+ this.take();
+ return statements;
+ }
+ parse() {
+ const declarations = [];
+ this.separators();
+ while (!this.is('eof')) {
+ const token = this.expect('name', 'declaration');
+ const kind = token.value;
+ if (kind === 'state') {
+ const name = this.expect('name', 'state name'); this.expect('=');
+ declarations.push({ kind, token, name, initial: this.initial() });
+ } else if (kind === 'record') {
+ const name = this.expect('name', 'record type'); this.newlines(); this.expect('{'); this.separators();
+ const fields = [];
+ while (!this.is('}')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,fields});
+ } else if (kind === 'item') {
+ const name = this.expect('name', 'item name'); this.expect('=');
+ const type = this.expect('name', 'record type'); this.expect('('); this.newlines();
+ const fields = [];
+ while (!this.is(')')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.newlines();
+ if (!this.is(',')) break;
+ this.take(); this.newlines();
+ }
+ this.expect(')'); declarations.push({kind,token,name,type,fields});
+ } else if (kind === 'rule') {
+ const name = this.expect('name', 'rule name'); this.expect('(');
+ const parameter = this.expect('name', 'record parameter'); this.expect(':');
+ const type = this.expect('name', 'record type'); this.expect(')');
+ declarations.push({kind,token,name,parameter,type,body:this.block()});
+ } else if (kind === 'input') {
+ const name = this.expect('name', 'input name'); this.expect('=');
+ const key = this.expect('name', 'keyboard code or pointer(view)');
+ if (key.value === 'value') {
+ declarations.push({kind,token,name,valueInput:true}); this.end(); continue;
+ }
+ if (key.value === 'pointer') {
+ if (this.is('{')) {
+ this.take(); this.separators(); const routes = [];
+ while (!this.is('}')) {
+ const target = this.expect('name', 'view ID'); this.expect(':');
+ const item = this.expect('name', 'item name'); routes.push({target,item}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,routes}); this.end(); continue;
+ }
+ this.expect('(');
+ const target = this.expect('name', 'view ID'); this.expect(')');
+ declarations.push({ kind, token, name, target });
+ this.end(); continue;
+ }
+ if (!/^(?:Space|Enter|Arrow(?:Left|Right|Up|Down)|Key[A-Z]|Digit[0-9])$/.test(key.value)) fail(key, 'Unsupported keyboard code');
+ declarations.push({ kind, token, name, key });
+ } else if (Object.hasOwn(VIEW_FIELDS, kind)) {
+ const name = this.expect('name', 'view ID'); this.expect('(');
+ const expressions = [];
+ for (let i = 0; i < VIEW_FIELDS[kind].length; i++) {
+ if (i) { this.newlines(); this.expect(','); }
+ expressions.push(this.expression(0, true));
+ }
+ this.newlines();
+ let color, prefix = '';
+ if (kind !== 'text') {
+ this.expect(','); this.newlines();
+ const value = this.expect('string', 'literal hex color');
+ if (!/^#[0-9a-fA-F]{6}$/.test(value.value)) fail(value, 'Color must use six hexadecimal digits, such as "#356548"');
+ color = value.value;
+ } else if (this.is(',')) { this.take(); this.newlines(); prefix = this.expect('string', 'literal text prefix').value; }
+ this.newlines(); this.expect(')');
+ declarations.push({ kind: 'view', type: kind, token, name, expressions, color, prefix });
+ } else if (kind === 'on') {
+ const event = this.expect('name', 'input name or frame');
+ let edge;
+ if (event.value !== 'frame') {
+ this.expect('.'); edge = this.expect('name', 'down, up, move or cancel');
+ if (!['down', 'up', 'move', 'cancel', 'change'].includes(edge.value)) fail(edge, 'Expected down or up, move, cancel or change');
+ }
+ if (this.is('name', 'use')) {
+ this.take(); const rule = this.expect('name', 'rule name'); this.expect('(');
+ const item = this.expect('name', 'item name or input.target');
+ const argument = this.reference(item); this.expect(')');
+ declarations.push({kind:'handler',token,event,edge,rule,item,argument});
+ } else declarations.push({ kind: 'handler', token, event, edge, body: this.block() });
+ } else fail(token, `Unknown declaration ${kind}`);
+ this.end();
+ }
+ return declarations;
+ }
+}
+
+export function compile(source) {
+ if (typeof source !== 'string') fail({ line: 1, column: 1 }, 'Source must be a string');
+ const sourceBytes = new TextEncoder().encode(source).length;
+ if (sourceBytes > LIMITS.sourceBytes) fail({ line: 1, column: 1 }, 'Source exceeds 32768 UTF-8 bytes');
+ const declarations = new Parser(lex(source)).parse();
+ const program = { states: [], inputs: [], instructions: [], handlers: [], views: [], pointerTargets: [], metrics: {} };
+ const states = new Map(), inputs = new Map(), views = new Set(), keys = new Set(), targets = new Set();
+ const records = new Map(), items = new Map(), rules = new Map();
+ const scalarNames = new Set(declarations.filter(d => d.kind === 'state').map(d => d.name.value));
+ for (const declaration of declarations) {
+ if (!['record','rule'].includes(declaration.kind)) continue;
+ const {name,fields,kind} = declaration, symbols = kind === 'record' ? records : rules;
+ if (RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (kind === 'record') {
+ if (!fields.length || fields.length > 8) fail(name, 'A record needs 1..8 fields');
+ const used = new Set();
+ for (const field of fields) {
+ if (used.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ if (RESERVED.has(field.name.value)) fail(field.name, `Reserved name ${field.name.value}`);
+ used.add(field.name.value);
+ }
+ }
+ symbols.set(name.value, declaration);
+ }
+ let handlerCount = 0;
+ for (const declaration of declarations) {
+ const { kind, name, token } = declaration;
+ if (name && RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (kind === 'record' || kind === 'rule') continue;
+ if (kind === 'item') {
+ if (items.has(name.value) || scalarNames.has(name.value)) fail(name, `Duplicate state/item ${name.value}`);
+ const record = records.get(declaration.type.value);
+ if (!record) fail(declaration.type, `Unknown record ${declaration.type.value}`);
+ const overrides = new Map();
+ for (const field of declaration.fields) {
+ if (!record.fields.some(f => f.name.value === field.name.value)) fail(field.name, `Unknown field ${field.name.value}`);
+ if (overrides.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ overrides.set(field.name.value, field.initial);
+ }
+ const base = states.size;
+ for (const field of record.fields) {
+ if (states.size >= LIMITS.states) fail(name, 'At most 32 states are allowed, including item fields');
+ const qualified = `${name.value}.${field.name.value}`, index = states.size;
+ states.set(qualified,index);
+ program.states.push({name:qualified,initial:overrides.has(field.name.value) ? overrides.get(field.name.value) : field.initial,line:token.line});
+ }
+ items.set(name.value,{type:declaration.type.value,base,count:record.fields.length});
+ } else if (kind === 'state' || kind === 'input') {
+ const symbols = kind === 'state' ? states : inputs;
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (symbols.size >= LIMITS[`${kind}s`]) fail(name, `At most ${LIMITS[`${kind}s`]} ${kind}s are allowed`);
+ symbols.set(name.value, symbols.size);
+ if (kind === 'state') program.states.push({ name: name.value, initial: declaration.initial, line: token.line });
+ else if (declaration.valueInput) {
+ program.inputs.push({name:name.value,kind:'value',line:token.line});
+ } else if (declaration.routes) {
+ if (!declaration.routes.length) fail(name, 'A pointer group needs at least one target');
+ program.inputs.push({name:name.value, routes:[], line:token.line});
+ } else if (declaration.target) {
+ const target = declaration.target;
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ targets.add(target.value);
+ program.inputs.push({ name: name.value, target: target.value, line: token.line });
+ } else {
+ if (keys.has(declaration.key.value)) fail(declaration.key, `Duplicate keyboard code ${declaration.key.value}`);
+ keys.add(declaration.key.value);
+ program.inputs.push({ name: name.value, key: declaration.key.value, line: token.line });
+ }
+ } else if (kind === 'view') {
+ if (views.has(name.value)) fail(name, `Duplicate view ID ${name.value}`);
+ if (views.size >= LIMITS.views) fail(name, 'At most 24 views are allowed');
+ views.add(name.value);
+ } else if (++handlerCount > LIMITS.handlers) fail(token, 'At most 64 handlers are allowed');
+ }
+ for (const declaration of declarations) {
+ if (declaration.target && !views.has(declaration.target.value))
+ fail(declaration.target, `Unknown pointer target ${declaration.target.value}`);
+ }
+ const routedItems = new Set();
+ for (const declaration of declarations) {
+ if (!declaration.routes) continue;
+ const input = inputs.get(declaration.name.value), resolved = program.inputs[input];
+ let type;
+ for (const {target,item:token} of declaration.routes) {
+ if (!views.has(target.value)) fail(target, `Unknown pointer target ${target.value}`);
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ const item = items.get(token.value);
+ if (!item) fail(token, `Unknown item ${token.value}`);
+ if (type && type !== item.type) fail(token, 'Pointer group targets must share one record type');
+ if (routedItems.has(token.value)) fail(token, `Item ${token.value} already has a pointer route`);
+ targets.add(target.value); routedItems.add(token.value); type = item.type;
+ const route = program.pointerTargets.length;
+ if (route >= 24) fail(target, 'At most 24 pointer targets are allowed');
+ program.pointerTargets.push({input,base:item.base,count:item.count});
+ resolved.routes.push({target:target.value, item:token.value, route});
+ }
+ resolved.type = type;
+ }
+ for (const rule of rules.values()) {
+ if (!records.has(rule.type.value)) fail(rule.type, `Unknown record ${rule.type.value}`);
+ if (RESERVED.has(rule.parameter.value)) fail(rule.parameter, `Reserved name ${rule.parameter.value}`);
+ }
+ let pointHandler = false, valueHandler = false;
+ let parameters = null;
+ let parameterPrefix = null;
+ let stack = 0, maxStack = 0;
+ const emit = (op, token, arg = 0, value = 0, delta = 0) => {
+ if (program.instructions.length >= LIMITS.instructions) fail(token, 'At most 512 instructions are allowed');
+ stack += delta;
+ if (stack < 0 || stack > LIMITS.stack) fail(token, 'Expression stack exceeds 64');
+ maxStack = Math.max(maxStack, stack);
+ program.instructions.push({ op, arg, value, line: token.line });
+ };
+ const expression = (node, binding = false) => {
+ const { token } = node;
+ if (node.kind === 'constant') emit(0, token, 0, node.value, 1);
+ else if (node.kind === 'reference') {
+ if (node.name === 'event_value') {
+ if (binding || !valueHandler) fail(token, 'event_value is only available in value change handlers');
+ emit(26, token, 0, 0, 1);
+ } else if (node.name === 'event_x' || node.name === 'event_y') {
+ if (binding || !pointHandler) fail(token, 'event_x and event_y are only available in pointer handlers');
+ emit(node.name === 'event_x' ? 22 : 23, token, 0, 0, 1);
+ } else if (node.name === 'dt') {
+ if (binding) fail(token, 'dt is only available in handlers');
+ emit(2, token, 0, 0, 1);
+ } else {
+ if (parameterPrefix && node.name.startsWith(parameterPrefix) && !parameters.has(node.name))
+ fail(token, `Unknown parameter field ${node.name}`);
+ if (parameters?.has(node.name)) {
+ emit(24, token, parameters.get(node.name), 0, 1);
+ return;
+ }
+ if (!states.has(node.name)) fail(token, `Unknown state ${node.name}`);
+ emit(1, token, states.get(node.name), 0, 1);
+ }
+ } else if (node.kind === 'unary') { expression(node.child, binding); emit(node.op, token); }
+ else if (node.kind === 'binary') {
+ expression(node.left, binding); expression(node.right, binding); emit(node.op, token, 0, 0, -1);
+ } else {
+ for (const arg of node.args) expression(arg, binding);
+ emit(node.op, token, 0, 0, 1 - node.args.length);
+ }
+ };
+ const statements = body => {
+ for (const statement of body) {
+ if (statement.kind === 'assign') {
+ if (parameterPrefix && statement.name.startsWith(parameterPrefix) && !parameters.has(statement.name))
+ fail(statement.token, `Unknown parameter field ${statement.name}`);
+ const parameter = parameters?.get(statement.name);
+ if (parameter === undefined && !states.has(statement.name)) fail(statement.token, `Unknown state ${statement.name}`);
+ expression(statement.expression);
+ emit(parameter === undefined ? 20 : 25, statement.token, parameter === undefined ? states.get(statement.name) : parameter, 0, -1);
+ } else {
+ expression(statement.condition);
+ const branch = program.instructions.length;
+ emit(21, statement.token, 0, 0, -1);
+ statements(statement.body);
+ program.instructions[branch].arg = program.instructions.length;
+ }
+ }
+ };
+ const bodies = new Map();
+ function ruleBody(rule) {
+ if (bodies.has(rule.name.value)) return bodies.get(rule.name.value);
+ parameterPrefix = `${rule.parameter.value}.`;
+ parameters = new Map(records.get(rule.type.value).fields.map((field,index) => [`${rule.parameter.value}.${field.name.value}`,index]));
+ // A shared body may read coordinates; every binding is checked below.
+ pointHandler = true; valueHandler = true; stack = 0;
+ const start = program.instructions.length;
+ statements(rule.body);
+ const length = program.instructions.length - start;
+ const point = program.instructions.slice(start).some(op => op.op === 22 || op.op === 23);
+ parameters = null; parameterPrefix = null;
+ const value = program.instructions.slice(start).some(op => op.op === 26);
+ const body = {start,length,point,value}; bodies.set(rule.name.value,body); return body;
+ }
+ for (const declaration of declarations) {
+ if (declaration.kind === 'handler') {
+ let event = 0;
+ pointHandler = false; valueHandler = false;
+ if (declaration.event.value !== 'frame') {
+ if (!inputs.has(declaration.event.value)) fail(declaration.event, `Unknown input ${declaration.event.value}`);
+ const index = inputs.get(declaration.event.value), edge = declaration.edge.value;
+ pointHandler = Boolean(program.inputs[index].target || program.inputs[index].routes);
+ valueHandler = program.inputs[index].kind === 'value';
+ if (valueHandler !== (edge === 'change')) fail(declaration.edge, 'Value inputs require change; change requires a value input');
+ if (!pointHandler && (edge === 'move' || edge === 'cancel')) fail(declaration.edge, 'move and cancel require a pointer input');
+ event = edge === 'change' ? 33 + index : edge === 'move' ? 17 + index : edge === 'cancel' ? 25 + index : 1 + index * 2 + (edge === 'up' ? 1 : 0);
+ }
+ if (declaration.rule) {
+ const rule = rules.get(declaration.rule.value);
+ const routed = declaration.argument.includes('.');
+ const input = program.inputs[inputs.get(declaration.event.value)];
+ if (routed && (!input?.routes || declaration.argument !== `${declaration.event.value}.target`))
+ fail(declaration.item, 'Use the current pointer group target');
+ const item = routed ? {type:input.type, count:records.get(input.type).fields.length} : items.get(declaration.item.value);
+ if (!rule) fail(declaration.rule, `Unknown rule ${declaration.rule.value}`);
+ if (!item) fail(declaration.item, `Unknown item ${declaration.item.value}`);
+ if (item.type !== rule.type.value) fail(declaration.item, `Rule ${rule.name.value} requires ${rule.type.value}`);
+ const pointer = pointHandler, value = valueHandler;
+ const body = ruleBody(rule);
+ if (body.value && !value) fail(declaration.rule, 'Value-reading rules require a value input');
+ if (body.point && !pointer) fail(declaration.rule, 'Coordinate-reading rules require a pointer input');
+ program.handlers.push({event,start:body.start,length:body.length,line:declaration.token.line,parameterBase:routed ? 255 : item.base,parameterCount:item.count});
+ } else {
+ const start = program.instructions.length;
+ stack = 0; statements(declaration.body);
+ program.handlers.push({ event, start, length: program.instructions.length - start, line: declaration.token.line });
+ }
+ } else if (declaration.kind === 'view') {
+ const view = { id: declaration.name.value, type: declaration.type, line: declaration.token.line, bindings: {} };
+ if (view.type === 'text') view.prefix = declaration.prefix;
+ else view.color = declaration.color;
+ declaration.expressions.forEach((node, index) => {
+ const start = program.instructions.length;
+ stack = 0; expression(node, true);
+ view.bindings[VIEW_FIELDS[view.type][index]] = { start, length: program.instructions.length - start };
+ });
+ program.views.push(view);
+ }
+ }
+ // Unused definitions still receive name/type checking, but reserve no VM body.
+ for (const rule of rules.values()) {
+ if (bodies.has(rule.name.value)) continue;
+ const instructions = program.instructions, previousMax = maxStack;
+ program.instructions = [];
+ ruleBody(rule);
+ program.instructions = instructions; maxStack = previousMax;
+ }
+ program.metrics = { sourceBytes, sourceLines: source === '' ? 0 : source.split('\n').length,
+ states: states.size, inputs: inputs.size, views: views.size,
+ handlers: program.handlers.length, instructions: program.instructions.length, maxStack };
+ return program;
+}
+
+export { LIMITS };
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/core.wasm b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/core.wasm
new file mode 100755
index 0000000..79c50a8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/core.wasm
Binary files differ
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/project.mjs b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/project.mjs
new file mode 100644
index 0000000..861e0fc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/project.mjs
@@ -0,0 +1,47 @@
+import { compile } from './compiler.mjs';
+
+// Two escaped source strings plus up to 32 generated item.field names. A long
+// schema field can appear in every item without repeating in the source text.
+export const MAX_PROJECT_BYTES = (2 * 6 + 32) * 32768 + 8192;
+const encoder = new TextEncoder();
+function sourceText(value, label) {
+ if (typeof value !== 'string' || encoder.encode(value).length > 32768)
+ throw new Error(`${label}: UTF-8 32 KiB 이하의 코드가 필요합니다.`);
+ return value;
+}
+
+// No runtime mutation. Validate every saved value before opening core staging.
+export function validateDocument(document) {
+ if (!document || typeof document !== 'object' || Array.isArray(document) ||
+ document.format !== 'pure-workbench' || document.version !== 2)
+ throw new Error('배치 파일 형식이 맞지 않습니다. pure-workbench version 2가 필요합니다.');
+ const source = sourceText(document.source, '적용된 코드');
+ const draft = sourceText(Object.hasOwn(document, 'draft') ? document.draft : source, '편집 중인 코드');
+ const program = compile(source);
+ if (!Array.isArray(document.states) || document.states.length !== program.states.length)
+ throw new Error('저장된 상태 목록이 적용된 코드와 일치하지 않습니다.');
+ const values = new Map();
+ for (const entry of document.states) {
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry) || typeof entry.name !== 'string' || values.has(entry.name))
+ throw new Error('상태 이름이 잘못됐거나 중복됐습니다.');
+ const value = entry.value === '-0' ? -0 : entry.value;
+ if (typeof value !== 'number' || !Number.isFinite(value)) throw new Error('상태 값은 유한한 숫자여야 합니다.');
+ values.set(entry.name, value);
+ }
+ for (const state of program.states)
+ if (!values.has(state.name)) throw new Error(`저장된 상태가 없습니다: ${state.name}`);
+ return { source, draft, program, values: program.states.map(state => values.get(state.name)) };
+}
+
+export function parseProject(text) {
+ if (typeof text !== 'string' || encoder.encode(text).length > MAX_PROJECT_BYTES)
+ throw new Error('작업 파일이 너무 큽니다.');
+ let project;
+ try { project = JSON.parse(text); } catch { throw new Error('올바른 JSON 파일이 아닙니다.'); }
+ if (!project || typeof project !== 'object' || Array.isArray(project) || project.format !== 'pure-workbench')
+ throw new Error('Pure 작업물 형식이 아닙니다.');
+ if (project.version === 1) sourceText(project.source, '코드');
+ else if (project.version === 2) validateDocument(project);
+ else throw new Error('지원하지 않는 작업 파일 버전입니다.');
+ return project;
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/runtime.mjs b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/runtime.mjs
new file mode 100644
index 0000000..d8d6618
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/sources/prototypes/workbench/web/runtime.mjs
@@ -0,0 +1,350 @@
+import { compile } from './compiler.mjs';
+import { validateDocument } from './project.mjs';
+
+const messages = [
+ '', '실행기의 용량 한도를 넘었습니다.', '실행 정의가 유효하지 않습니다.',
+ '계산 스택의 범위를 벗어났습니다.', '0으로 나눌 수 없습니다.',
+ '계산 결과가 유한한 수의 범위를 벗어났습니다.', '조건 분기 범위가 유효하지 않습니다.',
+ '존재하지 않는 상태를 참조했습니다.', '시간 간격이 유효하지 않습니다.',
+ '정의되지 않은 입력 사건입니다.',
+];
+const sourceLimit = 32768;
+
+function problem(message, line = null, column = null) {
+ return Object.assign(new Error(message), { line, column });
+}
+
+function freezeProgram(value) {
+ if (value && typeof value === 'object') {
+ for (const child of Object.values(value)) freezeProgram(child);
+ Object.freeze(value);
+ }
+ return value;
+}
+
+export async function createRuntime(wasmBytes, evaluationOptions = {}) {
+ if (wasmBytes === undefined) {
+ const response = await fetch(new URL('./core.wasm', import.meta.url), { cache: 'no-store' });
+ if (!response.ok) throw new Error(`실행기를 불러오지 못했습니다 (HTTP ${response.status}).`);
+ wasmBytes = await response.arrayBuffer();
+ }
+ const module = await WebAssembly.compile(wasmBytes);
+ if (WebAssembly.Module.imports(module).length) throw new Error('이 실행기는 호스트 함수 없이 동작해야 합니다.');
+ const { exports: core } = await WebAssembly.instantiate(module, {});
+ if (typeof core.eval_bounded !== 'function' || typeof core.abort_program !== 'function' || typeof core.dispatch_point !== 'function' || typeof core.put_restored_value !== 'function' || typeof core.commit_restored_program !== 'function' || typeof core.bind_handler !== 'function' || typeof core.put_pointer_target !== 'function' || typeof core.bind_target_handler !== 'function' || typeof core.dispatch_target !== 'function' || typeof core.dispatch_value !== 'function')
+ throw new Error('실행기 버전이 맞지 않습니다. 새로고침하거나 core.wasm을 다시 빌드하세요.');
+ core.reset_all();
+ let program = null;
+ let appliedSource = '';
+ let lastEvent = null;
+ // Keep a failed event visible through its release/focus-loss cleanup.
+ // The active program can clear this diagnostic by apply or explicit reset.
+ let lastFailure = null;
+ const held = new Map();
+ const points = new Map();
+ let presenting = false;
+ let bindings = [];
+ let pointRoutes = new Map();
+ // One bounded publication buffer, never exposed to callers. No state mirror.
+ let displayValues = null, displayValid = null;
+ function available() {
+ if (presenting) throw new Error('출력 전달 중에는 실행기를 다시 호출할 수 없습니다.');
+ }
+ let evaluationPolicy = { cacheEntries: 0, historyEntries: 8, workLimit: 2048 };
+
+ function checked(code, line = null) {
+ if (code !== 0) throw problem(messages[code] || `실행기 오류 ${code}`, line);
+ }
+ function inputIndex(name) {
+ const index = program?.inputs.findIndex((input) => input.name === name) ?? -1;
+ if (index < 0) throw new Error(`정의되지 않은 입력: ${name}`);
+ return index;
+ }
+ function dispatch(event, name, phase, source, point = null, value = undefined) {
+ const status = value !== undefined ? core.dispatch_value(event, value) : point ? (point.route === undefined ? core.dispatch_point(event, point.x, point.y)
+ : core.dispatch_target(event, point.route, point.x, point.y)) : core.dispatch(event, event === 0 ? 1 / 60 : 0);
+ const pc = core.info(2) >>> 0;
+ lastEvent = { name, phase, source, status,
+ line: program?.instructions[pc]?.line ?? null, ops: core.info(3) >>> 0 };
+ if (point) { lastEvent.x = point.x; lastEvent.y = point.y; if (point.target) lastEvent.target = point.target; }
+ if (value !== undefined) lastEvent.value = value;
+ if (status) lastFailure = { ...lastEvent };
+ return status;
+ }
+
+ function evaluateDisplay() {
+ core.begin_evaluation(evaluationPolicy.workLimit);
+ if (!bindings.length) return null;
+ displayValues ??= new Float64Array(96);
+ displayValid ??= new Uint8Array(24);
+ let error = null, slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ displayValid[i] = 1;
+ for (const [name, binding] of bindings[i]) {
+ const value = core.eval_bounded(binding.start, binding.length);
+ if (core.evaluation_info(0) === 10) {
+ displayValid.fill(0);
+ return { code: 101, line: view.line,
+ message: '표시 계산의 작업량 한도를 넘었습니다. 한도를 늘리거나 표시식을 줄이세요.' };
+ }
+ if (!Number.isFinite(value) || ((name === 'width' || name === 'height' || name === 'radius') && value < 0)) {
+ error ??= { line: view.line, message: `${view.id}.${name}: 표시할 수 없는 값입니다. 0 나눗셈이나 음수 크기를 확인하세요.` };
+ displayValid[i] = 0;
+ }
+ displayValues[slot++] = value;
+ }
+ }
+ return error;
+ }
+
+ function status(viewError) {
+ const executionError = lastFailure?.status || 0;
+ return {
+ tick: core.info(0) >>> 0, revision: core.info(4) >>> 0,
+ displayError: viewError ? { code: viewError.code || 100, ...viewError } : null,
+ lastError: executionError || (viewError ? viewError.code || 100 : 0),
+ errorMessage: executionError ? messages[executionError] || `실행 오류 ${executionError}` : viewError?.message || '',
+ errorLine: executionError ? lastFailure.line : viewError?.line ?? null,
+ lastOps: core.info(3) >>> 0, successfulEvents: core.info(9) >>> 0,
+ held: [...held.keys()], lastEvent: lastEvent ? { ...lastEvent } : null,
+ lastFailure: lastFailure ? { ...lastFailure } : null,
+ memory: {
+ linearBytes: core.memory.buffer.byteLength,
+ reservedEngineBytes: core.layout(0), programReservedBytes: core.layout(1),
+ instructionBytes: core.layout(2), handlerBytes: core.layout(3),
+ activeIRBytes: core.layout(4), activeStateBytes: core.layout(5),
+ stagingReservedBytes: core.layout(6), evalStackBytes: core.layout(7),
+ pointerTargetBytes: core.layout(8), pointerTargets: core.layout(9),
+ },
+ };
+ }
+
+ function load(next, source, restored = null) {
+ const oldIds = new Map(restored ? [] : program?.states.map((state, index) => [state.name, index]) ?? []);
+ checked(core.begin_program(next.states.length, next.inputs.length));
+ try {
+ for (let index = 0; index < next.states.length; index++) {
+ const state = next.states[index];
+ checked(core.put_state(index, state.initial, oldIds.get(state.name) ?? -1), state.line);
+ if (restored) checked(core.put_restored_value(index, restored[index]), state.line);
+ }
+ for (const op of next.instructions) checked(core.put_instruction(op.op, op.arg, op.value), op.line);
+ for (const target of next.pointerTargets) checked(core.put_pointer_target(target.input, target.base, target.count));
+ for (const [index, handler] of next.handlers.entries()) {
+ checked(core.put_handler(handler.event, handler.start, handler.length), handler.line);
+ if (handler.parameterCount)
+ checked(handler.parameterBase === 255 ? core.bind_target_handler(index, handler.parameterCount)
+ : core.bind_handler(index, handler.parameterBase, handler.parameterCount), handler.line);
+ }
+ checked(restored ? core.commit_restored_program() : core.commit_program());
+ } catch (error) {
+ core.abort_program();
+ throw error;
+ }
+ pointRoutes = new Map(next.inputs.flatMap(input => (input.routes ?? []).map(route => [route.target, route])));
+ program = next;
+ bindings = next.views.map(view => Object.entries(view.bindings));
+ appliedSource = source;
+ lastEvent = null;
+ lastFailure = null;
+ }
+
+ const api = {
+ get currentProgram() { return program; },
+ configureEvaluation({ cacheEntries = evaluationPolicy.cacheEntries,
+ historyEntries = evaluationPolicy.historyEntries, workLimit = evaluationPolicy.workLimit } = {}) {
+ available();
+ for (const [name, value, maximum] of [['cacheEntries', cacheEntries, 32],
+ ['historyEntries', historyEntries, 8], ['workLimit', workLimit, 0xffffffff]]) {
+ if (!Number.isInteger(value) || value < 0 || value > maximum)
+ throw new Error(`${name}: 0~${maximum} 사이의 정수여야 합니다.`);
+ }
+ checked(core.configure_evaluation(cacheEntries, historyEntries));
+ evaluationPolicy = { cacheEntries, historyEntries, workLimit };
+ return { ...evaluationPolicy };
+ },
+ forgetEvaluation(part = 'all') {
+ available();
+ const flags = part === 'all' ? 3 : part === 'values' ? 1 : part === 'history' ? 2 : undefined;
+ if (flags === undefined) throw new Error('삭제할 기록은 values, history, all 중 하나여야 합니다.');
+ core.forget_evaluation(flags);
+ },
+ evaluationStats() {
+ return { ...evaluationPolicy, work: core.evaluation_info(1),
+ instructions: core.evaluation_info(2), cacheHits: core.evaluation_info(3),
+ reservedBytes: core.evaluation_info(6), dedicatedBytes: core.evaluation_info(7),
+ sharedBytes: core.evaluation_info(8), reuseAvailable: Boolean(core.evaluation_info(9)),
+ workspaceTagBytes: core.evaluation_info(10) };
+ },
+ apply(source) {
+ available();
+ if (typeof source !== 'string' || new TextEncoder().encode(source).length > sourceLimit) {
+ throw problem('정의는 UTF-8 기준 32,768바이트 이하의 텍스트여야 합니다.');
+ }
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 적용하세요. 현재 작업은 그대로 유지합니다.');
+ const next = freezeProgram(compile(source));
+ load(next, source);
+ return next;
+ },
+ restoreDocument(document) {
+ available();
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 복원하세요.');
+ const next = validateDocument(document);
+ load(freezeProgram(next.program), next.source, next.values);
+ return { source: next.source, draft: next.draft };
+ },
+ exportDocument(draft = appliedSource) {
+ available();
+ if (!program) throw problem('먼저 코드를 적용하세요.');
+ if (held.size) throw problem('조작을 끝낸 뒤 배치를 저장하세요.');
+ if (lastFailure) throw problem('실행 오류를 해결한 뒤 배치를 저장하세요.');
+ if (typeof draft !== 'string' || new TextEncoder().encode(draft).length > sourceLimit)
+ throw problem('편집 중인 코드는 UTF-8 32 KiB 이하여야 합니다.');
+ return { format: 'pure-workbench', version: 2, source: appliedSource, draft,
+ states: program.states.map((state, i) => {
+ const value = core.get_state(i);
+ return { name: state.name, value: Object.is(value, -0) ? '-0' : value };
+ }) };
+ },
+ reset() {
+ available();
+ held.clear();
+ points.clear();
+ core.reset_state();
+ lastEvent = null;
+ lastFailure = null;
+ },
+ frame(count = 1) {
+ available();
+ if (!Number.isInteger(count) || count < 0 || count > 600) throw new Error('프레임 수는 0~600 사이의 정수여야 합니다.');
+ if (!program) return 0;
+ for (let i = 0; i < count; i++) {
+ const code = dispatch(0, 'frame', 'frame', 'clock');
+ if (code !== 0) return code;
+ }
+ return 0;
+ },
+ down(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name) || new Set();
+ if (sources.has(source)) return 0;
+ const wasDown = sources.size > 0;
+ sources.add(source);
+ held.set(name, sources);
+ return wasDown ? 0 : dispatch(1 + index * 2, name, 'down', source);
+ },
+ up(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name);
+ if (!sources?.delete(source)) return 0;
+ if (sources.size) return 0;
+ held.delete(name);
+ return dispatch(2 + index * 2, name, 'up', source);
+ },
+ change(name, value, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind !== 'value') throw new Error('숫자 값에 연결된 입력이 아닙니다.');
+ if (!Number.isFinite(value)) throw new Error('입력 값은 유한한 숫자여야 합니다.');
+ return dispatch(33 + index, name, 'change', source, null, value);
+ },
+ point(name, phase, x, y, source = 'external', target = undefined) {
+ available();
+ const index = inputIndex(name);
+ const input = program.inputs[index];
+ if (!input.target && !input.routes) throw new Error('포인터에 연결된 입력이 아닙니다.');
+ const route = input.routes ? pointRoutes.get(target) : undefined;
+ if (input.routes && (!route || program.pointerTargets[route.route].input !== index)) throw new Error('포인터 그룹에 연결된 도형 이름이 필요합니다.');
+ if (!input.routes && target !== undefined) throw new Error('단일 포인터 입력에는 대상 인자를 지정하지 않습니다.');
+ const owner = route ? `${name}:${target}` : name;
+ if (!['down', 'move', 'up', 'cancel'].includes(phase)) throw new Error('포인터 단계는 down, move, up, cancel 중 하나여야 합니다.');
+ if (!Number.isFinite(x) || !Number.isFinite(y)) throw new Error('포인터 좌표는 유한한 숫자여야 합니다.');
+ if (typeof source !== 'string' || source.length === 0) throw new Error('포인터 출처 이름이 필요합니다.');
+ let point = points.get(owner);
+ if (phase === 'down') {
+ if (point?.source === source) return 0;
+ if (point) throw new Error('이 입력은 다른 포인터가 사용 중입니다.');
+ point = {name, source, x, y, target, route:route?.route};
+ points.set(owner, point);
+ held.set(owner, new Set([source]));
+ } else {
+ if (!point || point.source !== source) return 0;
+ point.x = x; point.y = y;
+ if (phase === 'up' || phase === 'cancel') { points.delete(owner); held.delete(owner); }
+ }
+ const event = phase === 'move' ? 17 + index : phase === 'cancel' ? 25 + index : 1 + index * 2 + (phase === 'up' ? 1 : 0);
+ return dispatch(event, name, phase, source, point);
+ },
+ releaseAll() {
+ available();
+ let firstError = 0;
+ for (const point of [...points.values()]) {
+ const status = api.point(point.name, 'cancel', point.x, point.y, point.source, point.target);
+ if (!firstError) firstError = status;
+ }
+ for (const [name, sources] of [...held]) {
+ for (const source of [...sources]) {
+ const status = api.up(name, source);
+ if (!firstError) firstError = status;
+ }
+ }
+ return firstError;
+ },
+ exportProject() {
+ return { format: 'pure-workbench', version: 1, source: appliedSource };
+ },
+ // Synchronous trusted output adapter. Callbacks run only after the whole
+ // display has been evaluated. Runtime mutation/reentrant reads are refused.
+ // Exceptions from an adapter propagate; the next call republishes all values.
+ present(target) {
+ available();
+ presenting = true;
+ try {
+ const { begin, state, view, value, end } = target;
+ for (const callback of [begin, state, view, value, end])
+ if (typeof callback !== 'function') throw new TypeError('출력 어댑터 함수가 필요합니다.');
+ const error = evaluateDisplay();
+ begin.call(target, program);
+ for (let i = 0; i < (program?.states.length ?? 0); i++) state.call(target, i, core.get_state(i));
+ let slot = 0, visible = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const valid = Boolean(displayValid[i]);
+ view.call(target, i, valid);
+ for (const [name] of bindings[i]) {
+ if (valid) value.call(target, i, name, displayValues[slot]);
+ slot++;
+ }
+ if (valid) visible++;
+ }
+ end.call(target, visible);
+ return status(error);
+ } finally { presenting = false; }
+ },
+ snapshot() {
+ available();
+ const error = evaluateDisplay();
+ const states = Object.fromEntries((program?.states ?? []).map((state, index) => [state.name, core.get_state(index)]));
+ const views = [];
+ let slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ const rendered = displayValid[i] ? { id: view.id, type: view.type, color: view.color, prefix: view.prefix } : null;
+ for (const [name] of bindings[i]) {
+ if (rendered) rendered[name] = displayValues[slot];
+ slot++;
+ }
+ if (rendered) views.push(rendered);
+ }
+ return { states, views, ...status(error) };
+ },
+ };
+ api.configureEvaluation(evaluationOptions);
+ return Object.freeze(api);
+}
diff --git a/prototypes/connections/results/2026-09-23-execution-core/verification.json b/prototypes/connections/results/2026-09-23-execution-core/verification.json
new file mode 100644
index 0000000..ad430f8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-execution-core/verification.json
@@ -0,0 +1,30 @@
+{
+ "sources_verified_and_frozen": 30,
+ "native_and_sanitized_binaries_match": true,
+ "tcp_scenarios_per_build": 28,
+ "all_http_runs_drained": true,
+ "core_archive_external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "core_archive_sha256": "59eccbea380378a6650c59a99eacd92132184e5b9aa64feada7a176cf03ccfcc",
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 4892\t 0\t 0\t 4892\t 131c\t/home/eunhhu/work/pure/prototypes/connections/build/runtime.o\n 780\t 0\t 0\t 780\t 30c\t/home/eunhhu/work/pure/prototypes/connections/build/evaluate.o\n 41144\t 1048\t 16\t 42208\t a4e0\t/home/eunhhu/work/pure/prototypes/connections/build/pure-connections\n",
+ "compiler": "cc (Debian 14.2.0-19) 14.2.0",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "structure_sizes": {
+ "runtime_tests": "passed",
+ "domain_bytes": 192,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 648,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "limits": [
+ "synchronous storage effects",
+ "one owner thread",
+ "storage authoring profile only",
+ "no TLS or native UI yet",
+ "sizes are not process RSS or performance comparisons"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/README.md b/prototypes/connections/results/2026-09-23-field-connections/README.md
new file mode 100644
index 0000000..d516556
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/README.md
@@ -0,0 +1,31 @@
+# 021 검증 자료
+
+이름 기반 필드와 실제 입력 값으로 계산하는 구간을 네이티브 저장·응답에 연결한 기록이다.
+시간·처리량·전체 RSS 비교는 하지 않았다.
+
+- [native.json](native.json): 일반 빌드의 28개 통합 시나리오, 준비 결과, 자원 회수, 소스·실행 파일 해시.
+- [sanitized.json](sanitized.json): ASan·UBSan 빌드의 같은 시나리오. 누수 검사를 끄지 않았다.
+- [verification.json](verification.json): 명령, 세 단위 검사 결과, 소스 사본·실행 파일 일치 확인.
+- `sources/`: 기록된 소스·예제·클라이언트·Wasm 사본. 이후 작업 트리가 바뀌면 별도 트리에 배치해 재현한다.
+
+기존 22개 검사에 6개 필드 시나리오를 추가했다. 실제 예제 클라이언트가 한글·이모지 문서의
+문자 위치를 바이트 위치로 바꿔 전송하고, 네이티브 서버가 필드 값에 따라 선택·저장·응답한다.
+잘린 헤더·잘못된 범위·정렬되지 않은 숫자·바뀐 필드 순서·빈 선택·사용하지 않는 계산의 오류를
+확인한다. 별칭은 추가 동적 단계를 만들지 않으며, 느린 응답 동안 원본 수신 할당을 유지·계상한다.
+
+`field_connections`에는 선언에서 준비한 실제 접근 위치·데이터 의존 단계가 있다. `steps`의
+source_step 0은 입력의 정적 구간이고 양수는 앞 단계의 결과다. offset/length의 from_u32le가
+참이면 value는 입력에서 숫자를 읽을 위치이며, 거짓이면 상수다. write_step/reply_step이 양수인
+결과는 정적 offset/length 대신 해당 단계에서 정한다. 진단의 이전 whole 표기는 to_end로 바뀌었다.
+
+`runtime_view_steps`는 준비된 단계 수로 실행 시간 계측값이 아니다. `prepared_program_bytes`
+648 B는 고정 구조체 하나의 크기이며 사용하지 않는 동적 단계 자리도 포함한다. 기존 112 B보다
+536 B 늘어난 기능 비용이다. 논리적 본문 예산에는 OS·페이지·클라이언트 메모리가 포함되지 않는다.
+
+`test-flow`는 기존 저장·전송 의미를, `test-program`은 상수 구간 준비 의미를,
+`test-fields`는 필드 타입·배치·숫자·동적 범위·한도를 검사한다. 일반/검사 빌드 모두 통과했다.
+
+[구현 README](../../README.md)의 `make check`로 재현한다. `EVIDENCE=/새/경로.json`으로
+새 원자료를 남기며 기존 파일을 덮어쓰지 않는다. 이 환경에서는 소켓·자식 프로세스·
+LeakSanitizer의 샌드박스 제한 때문에 승인된 환경에서 로컬 검사를 실행했다.
+외부 서비스·macOS·실제 전원 장애·대규모 서비스는 검증하지 않았다.
diff --git a/prototypes/connections/results/2026-09-23-field-connections/native.json b/prototypes/connections/results/2026-09-23-field-connections/native.json
new file mode 100644
index 0000000..2d8ff24
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/native.json
@@ -0,0 +1,488 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 648,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ]
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 648,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ]
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ }
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 18,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 39824
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "binary_sha256": "d478daf835c30152d05aeba6d2c07dd598166129f18cc5f7cb3b893966b60a18",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "b7e7d6806cf9785df1d01f2418d1e493eaf2d4b9cf43abc90082c60bd61dcd0b",
+ "prototypes/connections/store.h": "03e23e349a19ffc3491d1bb9e4200b834cedf84a3f026613470a37a727ded11e",
+ "prototypes/connections/program.c": "54df0c5cd4579f64b2f32b965c520e2a4f36794cd3dece944d062454dc01df63",
+ "prototypes/connections/program.h": "2c3c955967883a9a8ea4566a006eccd44f3a173ac0682c2f272d09700f209639",
+ "prototypes/connections/server.c": "b905fa656fa626111ba765d6379aa03bd32fee97d19d48461cd752e75918ea31",
+ "prototypes/connections/check.py": "bf890ee92009fd57afcb6708ad325af360bf43a7c667c79c5dc90631889f5a3f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "8c0353ae6643351ba69505de4092aa40e34e5318f27d670de944cd875c4d51cc",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sanitized.json b/prototypes/connections/results/2026-09-23-field-connections/sanitized.json
new file mode 100644
index 0000000..1fbb30f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sanitized.json
@@ -0,0 +1,488 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 648,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ]
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 648,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ]
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 648,
+ "steps": []
+ }
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 18,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 39824
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 39824
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "binary_sha256": "be8a599f33d340e04f9269de9cc9b66d817aea567ca9a26a6a26258c2011ed91",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "b7e7d6806cf9785df1d01f2418d1e493eaf2d4b9cf43abc90082c60bd61dcd0b",
+ "prototypes/connections/store.h": "03e23e349a19ffc3491d1bb9e4200b834cedf84a3f026613470a37a727ded11e",
+ "prototypes/connections/program.c": "54df0c5cd4579f64b2f32b965c520e2a4f36794cd3dece944d062454dc01df63",
+ "prototypes/connections/program.h": "2c3c955967883a9a8ea4566a006eccd44f3a173ac0682c2f272d09700f209639",
+ "prototypes/connections/server.c": "b905fa656fa626111ba765d6379aa03bd32fee97d19d48461cd752e75918ea31",
+ "prototypes/connections/check.py": "bf890ee92009fd57afcb6708ad325af360bf43a7c667c79c5dc90631889f5a3f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "8c0353ae6643351ba69505de4092aa40e34e5318f27d670de944cd875c4d51cc",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/Makefile b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/Makefile
new file mode 100644
index 0000000..110acab
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/Makefile
@@ -0,0 +1,28 @@
+CC ?= cc
+CFLAGS ?= -O2 -g
+CFLAGS += -std=c17 -Wall -Wextra -Wpedantic -Werror
+BUILD ?= build
+
+.PHONY: all check
+all: $(BUILD)/pure-connections
+
+$(BUILD):
+ mkdir -p $@
+
+$(BUILD)/pure-connections: server.c store.c flow.c program.c store.h flow.h program.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) server.c store.c flow.c program.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-flow: test-flow.c store.c flow.c store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_STORE_TEST test-flow.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-program: test-program.c program.c program.h store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-program.c program.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-fields: test-fields.c program.c program.h store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-fields.c program.c $(LDFLAGS) $(LDLIBS) -o $@
+
+check: $(BUILD)/test-flow $(BUILD)/test-program $(BUILD)/test-fields $(BUILD)/pure-connections
+ $(BUILD)/test-flow
+ $(BUILD)/test-program
+ $(BUILD)/test-fields
+ python3 check.py --server $(BUILD)/pure-connections $(if $(EVIDENCE),--output "$(EVIDENCE)")
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/check.py b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/check.py
new file mode 100644
index 0000000..5c6a463
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/check.py
@@ -0,0 +1,528 @@
+#!/usr/bin/env python3
+"""Exercise local TCP, immutable byte extents, and the existing workbench CLI."""
+import argparse
+from contextlib import contextmanager
+from concurrent.futures import ThreadPoolExecutor
+import fcntl
+import hashlib
+import http.client
+import json
+import platform
+from pathlib import Path
+import select
+import socket
+import struct
+import subprocess
+import sys
+import tempfile
+import time
+
+ROOT = Path(__file__).resolve().parent
+WORKBENCH = ROOT.parent / 'workbench'
+OBJECT_LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+class Server:
+ def __init__(self, binary, storage, budget=4 * 1024 * 1024, timeout=5000, program=None):
+ self.process = subprocess.Popen([str(binary), '--store', str(storage), '--port', '0',
+ '--program', str(program or ROOT / 'examples/storage.pure'),
+ '--budget', str(budget), '--timeout-ms', str(timeout), '--send-buffer', '4096'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
+ if not select.select([self.process.stdout], [], [], 15)[0]:
+ self.process.kill()
+ raise AssertionError('server readiness timed out')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.ready = json.loads(line)
+ self.port = self.ready['port']
+ self.stats = None
+
+ def close(self):
+ if self.process.poll() is None:
+ self.process.terminate()
+ try:
+ stdout, stderr = self.process.communicate(timeout=10)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.process.communicate()
+ raise
+ assert self.process.returncode == 0, (stdout, stderr)
+ self.stats = json.loads(stderr)
+ assert self.stats['active'] == self.stats['retained_payload_bytes'] == 0
+ assert self.stats['peak_retained_payload_bytes'] <= self.stats['payload_budget']
+ assert self.stats['peak_connections'] <= 8
+
+
+@contextmanager
+def serving(*args, **kwargs):
+ server = Server(*args, **kwargs)
+ try:
+ yield server
+ finally:
+ server.close()
+
+
+def rpc(server, method, key, body=b'', expected=None):
+ headers = {'Content-Length': str(len(body))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = '*' if expected == 0 else f'"{expected}"'
+ connection = http.client.HTTPConnection('127.0.0.1', server.port, timeout=8)
+ try:
+ connection.request(method, f'/objects/{key}', body, headers)
+ response = connection.getresponse()
+ return response.status, dict(response.getheaders()), response.read()
+ finally:
+ connection.close()
+
+
+def wire(server, request, chunks=None):
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ if chunks:
+ for chunk in chunks:
+ sock.sendall(chunk)
+ else:
+ sock.sendall(request)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ return response.status, dict(response.getheaders()), response.read()
+
+
+def header(method, key, size=0, condition=b''):
+ return (f'{method} /objects/{key} HTTP/1.1\r\nHost: localhost\r\n'
+ f'Content-Length: {size}\r\n'.encode() + condition + b'\r\n')
+
+
+def cli(server, commands, source=None, expected_code=0):
+ result = subprocess.run(['node', str(WORKBENCH / 'cli.mjs'), *([str(source)] if source else [])],
+ input=commands.replace('$URL', f'http://127.0.0.1:{server.port}'), text=True,
+ capture_output=True, timeout=30)
+ assert result.returncode == expected_code, (result.stdout, result.stderr)
+ return [json.loads(line) for line in result.stdout.splitlines()], result.stderr
+
+
+def check(binary, directory):
+ storage = directory / 'objects'
+ checks, records = [], []
+ with serving(binary, storage) as server:
+ assert rpc(server, 'GET', 'absent')[0] == 404
+ payload = b'\x00\xffbinary\r\n\r\n' + bytes(range(256)) * 41
+ request = header('PUT', 'binary', len(payload), b'If-None-Match: *\r\n') + payload
+ status, headers, _ = wire(server, request, [request[:7], request[7:51], request[51:57], request[57:]])
+ assert status == 200 and headers['ETag'] == '"1"'
+ assert rpc(server, 'GET', 'binary')[2] == payload
+ checks.append('fragmented request and binary bytes round trip')
+ assert rpc(server, 'PUT', 'binary', b'new', 0)[0] == 412
+ assert rpc(server, 'PUT', 'binary', b'new', 1)[0] == 200
+ assert rpc(server, 'PUT', 'binary', b'stale', 1)[0] == 412
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('conditional create and stale revision preserve committed bytes')
+
+ with (storage / '.writer.lock').open('r+b') as lock:
+ fcntl.lockf(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ assert rpc(server, 'PUT', 'binary', b'blocked', 2)[0] == 503
+ fcntl.lockf(lock, fcntl.LOCK_UN)
+ broken = storage / 'obj-broken'
+ broken.write_bytes(b'incomplete')
+ assert rpc(server, 'GET', 'broken')[0] == 500
+ assert rpc(server, 'PUT', 'broken', b'failure', 0)[0] == 500
+ assert broken.read_bytes() == b'incomplete'
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('writer contention and invalid extent fail without overwriting data')
+
+ with serving(binary, storage) as second_writer:
+ with ThreadPoolExecutor(max_workers=2) as pool:
+ tasks = [pool.submit(rpc, target, 'PUT', 'race', value, 0)
+ for target, value in [(server, b'first'), (second_writer, b'second')]]
+ statuses = [task.result()[0] for task in tasks]
+ assert statuses.count(200) == 1 and all(status in [200, 412, 503] for status in statuses)
+ status, headers, body = rpc(server, 'GET', 'race')
+ assert status == 200 and headers['ETag'] == '"1"' and body in [b'first', b'second']
+ records.append(second_writer.stats)
+ checks.append('two native writers cannot both create the same expected revision')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'incomplete', 100, b'If-None-Match: *\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ sock.close()
+ assert rpc(server, 'GET', 'incomplete')[0] == 404
+ checks.append('incomplete request never commits and releases its allocation')
+
+ # Force genuine partial socket sends. A write on another connection must
+ # not alter the immutable file whose bytes are still being transmitted.
+ large = bytes(range(256)) * 4096
+ assert rpc(server, 'PUT', 'large', large, 0)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.getheader('ETag') == '"1"'
+ assert response.read(17) == large[:17]
+ assert rpc(server, 'PUT', 'large', b'changed', 1)[0] == 200
+ assert response.read() == large[17:]
+ sock.close()
+ assert rpc(server, 'GET', 'large')[2] == b'changed'
+ checks.append('borrowed read remains the same snapshot during another commit')
+
+ assert rpc(server, 'PUT', 'large', large, 2)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ assert sock.recv(1)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ sock.close()
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('receiver reset aborts an outstanding borrowed transfer')
+
+ assert wire(server, header('PUT', 'too_large', OBJECT_LIMIT + 1, b'If-None-Match: *\r\n'))[0] == 413
+ malformed = [
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nContent-Length: 1\r\nContent-Length: 1\r\nIf-None-Match: *\r\n\r\nx',
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n',
+ b'GET /objects/bad HTTP/1.1\r\nHost: x\x00hidden\r\n\r\n',
+ ]
+ for request in malformed:
+ assert wire(server, request)[0] == 400
+ assert rpc(server, 'GET', 'bad')[0] == 404
+ checks.append('unsupported framing and oversized payload are rejected before effects')
+
+ # Existing authoring path: define, manipulate, save remotely, reconstruct
+ # in a fresh runtime. No fabricated project fixture or mock storage.
+ source = WORKBENCH / 'examples' / 'direct.pure'
+ saved = directory / 'restored.json'
+ lines, _ = cli(server, 'point drag down 80 180\npoint drag move 210 210\npoint drag up 210 210\n'
+ 'connect $URL authored\npush 0\nquit\n', source)
+ snapshots = [line for line in lines if 'states' in line]
+ assert snapshots
+ expected_states = snapshots[-1]['states']
+ assert expected_states['x'] == 210 and expected_states['y'] == 190 and expected_states['dragging'] == 0
+ lines, _ = cli(server, f'connect $URL authored\npull\nsave-project {saved}\nquit\n')
+ assert [line for line in lines if 'states' in line][-1]['states'] == expected_states
+ document = json.loads(saved.read_text())
+ assert document['version'] == 2 and document['source'] == source.read_text()
+ lines, error = cli(server, 'connect $URL authored\npush 0\nquit\n', source, 1)
+ assert '412' in error
+ checks.append('existing workbench manipulation restores in a fresh runtime and reports conflict')
+
+ assert rpc(server, 'PUT', 'invalid_project', b'{"format":"pure-workbench","version":2,"source":"state x=1","states":[]}', 0)[0] == 200
+ lines, error = cli(server, 'show\nconnect $URL invalid_project\npull\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and error
+ lines, error = cli(server, 'point drag down 90 170\nconnect $URL authored\npull\npush\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and states[-1]['dragging'] == 1
+ assert len(error.strip().splitlines()) == 2
+ checks.append('invalid or non-idle restore preserves local state and does not adopt remote revision')
+
+ assert rpc(server, 'PUT', 'wide_revision', rpc_bytes(saved), 0)[0] == 200
+ wide = storage / 'obj-wide_revision'
+ raw = wide.read_bytes()
+ wide.write_bytes(raw[:8] + struct.pack('<Q', 9007199254740993) + raw[16:])
+ lines, _ = cli(server, 'connect $URL wide_revision\npull\npush\nquit\n')
+ revisions = [line['revision'] for line in lines if 'remote' in line and 'revision' in line]
+ assert revisions == ['9007199254740993', '9007199254740994']
+ checks.append('revision above JavaScript safe integer round trips without numeric coercion')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'unread_ack', 4, b'If-None-Match: *\r\n') + b'done')
+ try:
+ deadline = time.monotonic() + 3
+ while True:
+ committed = storage / 'obj-unread_ack'
+ if committed.exists():
+ assert committed.read_bytes()[24:] == b'done'
+ break
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ finally:
+ sock.close() # Client never consumes the successful response.
+ assert rpc(server, 'PUT', 'unread_ack', b'again', 0)[0] == 412
+ assert rpc(server, 'GET', 'unread_ack')[2] == b'done'
+ checks.append('unread acknowledgment does not undo commit or permit a stale retry')
+
+ # A disconnect after commit can hide the ACK; retries remain conditional.
+ assert rpc(server, 'PUT', 'empty', b'', 0)[0] == 200
+ assert rpc(server, 'GET', 'empty')[2] == b''
+ checks.append('empty body has a valid lifetime and stored revision')
+ records.append(server.stats)
+
+ with serving(binary, storage) as restarted:
+ assert rpc(restarted, 'GET', 'binary')[2] == b'new'
+ assert rpc(restarted, 'GET', 'authored')[2] == rpc_bytes(saved)
+ checks.append('committed authoring state survives process restart')
+ records.append(restarted.stats)
+
+ # Fixed small payload budget is an admission test, not a throughput workload.
+ with serving(binary, storage, budget=1024 * 1024, timeout=1200) as limited:
+ sock = socket.create_connection(('127.0.0.1', limited.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200
+ assert response.read(1) == large[:1]
+ status, headers, _ = rpc(limited, 'GET', 'large')
+ assert status == 503 and headers['X-Pure-Error'] == 'payload_budget'
+ # Leave the first receiver stalled until the absolute connection deadline.
+ time.sleep(1.4)
+ assert rpc(limited, 'GET', 'binary')[2] == b'new'
+ response.close()
+ sock.close()
+ checks.append('slow consumer retains its lease; budget rejects another; deadline releases it')
+
+ idle = [socket.create_connection(('127.0.0.1', limited.port), timeout=8) for _ in range(8)]
+ try:
+ for s in idle:
+ s.sendall(b'G')
+ for s in idle:
+ assert s.recv(1) == b''
+ finally:
+ for s in idle:
+ s.close()
+ assert rpc(limited, 'GET', 'binary')[0] == 200
+ checks.append('connection slots stay bounded and recover after header deadlines')
+ assert limited.stats['budget_rejections'] >= 1 and limited.stats['expired'] >= 9
+ records.append(limited.stats)
+ prepared = authored_connections(binary, directory, storage, records, checks)
+ fields = field_connections(binary, directory, storage, records, checks)
+ return {'kind': 'prepared-connection-correctness-not-performance', 'checks': checks,
+ 'prepared_connections': prepared,
+ 'field_connections': fields,
+ 'server_runs': records, 'storage': server.ready['storage']}
+
+
+def authored_connections(binary, directory, storage, records, checks):
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); }'
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); }'
+
+ def author(name, source):
+ path = directory / name
+ path.write_text(source)
+ return path
+
+ def explain(path):
+ return json.loads(subprocess.check_output([str(binary), '--check-program', str(path)], text=True))
+
+ with serving(binary, storage) as writer:
+ assert rpc(writer, 'PUT', 'short_parent', bytes(range(48)), 0)[0] == 200
+ assert rpc(writer, 'PUT', 'short_unused', bytes(range(80)), 0)[0] == 200
+ records.append(writer.stats)
+ excerpt = ROOT / 'examples/excerpt.pure'
+ prepared = {'excerpt': explain(excerpt)}
+ assert prepared['excerpt']['read'] == {
+ 'to_end': False, 'offset': 32, 'length': 16, 'minimum_source_bytes': 80}
+ with serving(binary, storage, budget=16, program=excerpt) as selected:
+ status, headers, body = rpc(selected, 'GET', 'large')
+ assert status == 200 and body == bytes(range(32, 48)) and headers['ETag'] == '"3"'
+ # Final [32,48) fits, but the authored parent [16,80) does not.
+ assert rpc(selected, 'GET', 'short_parent')[0] == 413
+ assert rpc(selected, 'GET', 'missing')[0] == 404
+ assert selected.stats['peak_retained_payload_bytes'] == 16
+ records.append(selected.stats)
+ checks.append('authored nested read maps only final demand while preserving parent bounds and revision')
+
+ unused = author('unused.pure', 'on get { let o = store.read(request.key); '
+ 'let unused = range(o.body, 0, 96); let body = range(o.body, 32, 16); reply(o, body); } ' + put)
+ with serving(binary, storage, budget=16, program=unused) as guarded:
+ assert rpc(guarded, 'GET', 'short_unused')[0] == 413
+ assert rpc(guarded, 'GET', 'large')[2] == bytes(range(32, 48))
+ records.append(guarded.stats)
+ checks.append('unused checked view still fails even when response range would be valid')
+
+ select_write = author('write.pure', get + ' on put { let a = range(request.body, 2, 10); '
+ 'let b = range(a, 3, 4); let alias = b; '
+ 'let saved = store.write(request.key, request.revision, alias); reply(saved, b); }')
+ prepared['write'] = explain(select_write)
+ with serving(binary, storage, program=select_write) as writer:
+ status, headers, body = rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'GET', 'selected')[2] == b'5678'
+ assert rpc(writer, 'PUT', 'selected', b'012345678', 1)[0] == 413
+ status, headers, body = rpc(writer, 'GET', 'selected')
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)[0] == 412
+ records.append(writer.stats)
+ checks.append('authored write and reply share selected input; invalid parent prevents the storage effect')
+
+ metadata = author('metadata.pure', 'on get { let o = store.read(request.key); reply(o); } ' + put)
+ with serving(binary, storage, budget=1, program=metadata) as meta:
+ status, headers, body = rpc(meta, 'GET', 'large')
+ assert status == 200 and headers['ETag'] == '"3"' and body == b''
+ assert rpc(meta, 'GET', 'absent')[0] == 404
+ assert rpc(meta, 'GET', 'broken')[0] == 500
+ assert meta.stats['peak_retained_payload_bytes'] == 0
+ records.append(meta.stats)
+ checks.append('body-free response preserves read existence and malformed-object errors')
+
+ echo = author('echo.pure', get + ' on put { let body = request.body; '
+ 'let saved = store.write(request.key, request.revision, body); reply(saved, body); }')
+ payload = bytes(range(256)) * 4096
+ with serving(binary, storage, budget=len(payload), program=echo) as echoed:
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == payload[:1]
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ assert response.read() == payload[1:]
+ response.close()
+ assert rpc(echoed, 'GET', 'binary')[2] == b'new'
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo_abort', len(payload), b'If-None-Match: *\r\n') + payload)
+ assert sock.recv(1)
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ deadline = time.monotonic() + 3
+ while rpc(echoed, 'GET', 'binary')[0] == 503:
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ assert rpc(echoed, 'GET', 'echo_abort')[2] == payload
+ records.append(echoed.stats)
+ checks.append('input-backed response survives partial send and releases on finish or abort without undoing commit')
+
+ bad = author('invalid.pure', get + get + put)
+ untouched = directory / 'must_not_exist'
+ rejected = subprocess.run([str(binary), '--program', str(bad), '--store', str(untouched)],
+ capture_output=True, text=True, timeout=10)
+ assert rejected.returncode == 2 and 'duplicate handler' in rejected.stderr and not untouched.exists()
+ checks.append('invalid authored program fails preparation before creating storage or accepting requests')
+ return prepared
+
+
+def field_connections(binary, directory, storage, records, checks):
+ program = ROOT / 'examples/selection.pure'
+ plans = {'selection': json.loads(subprocess.check_output(
+ [str(binary), '--check-program', str(program)], text=True))}
+ assert plans['selection']['runtime_view_steps'] == 1
+ assert plans['selection']['steps'][0] == {
+ 'source_step': 0, 'source': {'offset': 8, 'length': 0, 'to_end': True},
+ 'offset': {'value': 0, 'from_u32le': True}, 'length': {'value': 4, 'from_u32le': True}}
+ document = '처음🙂 Pure는 필드를 연결한다.\n끝'
+ document_file = directory / 'document.txt'
+ document_file.write_bytes(document.encode('utf-8'))
+ with serving(binary, storage, program=program) as selected:
+ command = [sys.executable, str(ROOT / 'examples/select-text.py'), str(document_file),
+ '--key', 'text_selection', '--start', '2', '--end', '12', '--url', f'http://127.0.0.1:{selected.port}']
+ result = subprocess.run(command, capture_output=True, text=True, timeout=15)
+ assert result.returncode == 0, (result.stdout, result.stderr)
+ expected = document[2:12].encode('utf-8')
+ assert json.loads(result.stdout) == {'revision': '1', 'selected': document[2:12], 'stored_bytes': len(expected)}
+ assert rpc(selected, 'GET', 'text_selection')[2] == expected
+ checks.append('text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes')
+
+ # Validation precedes the write: even a stale header cannot expose or
+ # commit partial input, and prior content/revision survive all failures.
+ invalid = [b'\0' * n for n in range(8)] + [
+ struct.pack('<II', 0xffffffff, 0) + b'abc',
+ struct.pack('<II', 0, 0xffffffff) + b'abc',
+ struct.pack('<II', 2, 2) + b'abc',
+ struct.pack('<II', 4, 0) + b'abc']
+ for payload in invalid:
+ assert rpc(selected, 'PUT', 'text_selection', payload, 1)[0] == 413
+ status, headers, body = rpc(selected, 'GET', 'text_selection')
+ assert status == 200 and headers['ETag'] == '"1"' and body == expected
+ for key, payload in [('selection_empty', struct.pack('<II', 0, 0)),
+ ('selection_end', struct.pack('<II', 3, 0) + b'abc')]:
+ assert rpc(selected, 'PUT', key, payload, 0)[0] == 200
+ assert rpc(selected, 'GET', key)[2] == b''
+ assert rpc(selected, 'PUT', 'text_selection', struct.pack('<II', 0, 3) + b'abc', 0)[0] == 412
+ checks.append('truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid')
+ records.append(selected.stats)
+
+ declaration = 'layout E { tag: bytes[3]; count: u32le; start: u32le; document: bytes; } '
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); } '
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); } '
+ reordered = directory / 'reordered.pure'
+ reordered.write_text(declaration + get + 'on put { let e = view(E, request.body); let alias = e; '
+ 'let part = range(alias.document, alias.start, alias.count); let again = part; '
+ 'let s = store.write(request.key, request.revision, again); reply(s, part); }')
+ plans['reordered'] = json.loads(subprocess.check_output([str(binary), '--check-program', str(reordered)], text=True))
+ assert plans['reordered']['runtime_view_steps'] == 1
+ with serving(binary, storage, program=reordered) as moved:
+ status, headers, body = rpc(moved, 'PUT', 'reordered', b'tag' + struct.pack('<II', 4, 2) + b'abcdefgh', 0)
+ assert status == 200 and body == b'cdef' and headers['ETag'] == '"1"'
+ assert rpc(moved, 'GET', 'reordered')[2] == b'cdef'
+ records.append(moved.stats)
+ checks.append('changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps')
+
+ unused = directory / 'unused-dynamic.pure'
+ unused.write_text(declaration + get + 'on put { let e = view(E, request.body); '
+ 'let unused = range(e.document, e.start, e.count); '
+ 'let s = store.write(request.key, request.revision, e.document); reply(s); }')
+ with serving(binary, storage, program=unused) as guarded:
+ assert rpc(guarded, 'PUT', 'unused_dynamic', b'tag' + struct.pack('<II', 4, 2) + b'abc', 0)[0] == 413
+ assert rpc(guarded, 'GET', 'unused_dynamic')[0] == 404
+ assert rpc(guarded, 'PUT', 'unused_dynamic', b'tag' + struct.pack('<II', 1, 1) + b'abc', 0)[0] == 200
+ assert rpc(guarded, 'GET', 'unused_dynamic')[2] == b'abc'
+ records.append(guarded.stats)
+ checks.append('unused dynamic field selection retains its validation before the write effect')
+
+ field_get = directory / 'field-get.pure'
+ field_get.write_text(declaration + 'on get { let o = store.read(request.key); '
+ 'let e = view(E, o.body); reply(o, e.document); } ' + put)
+ plans['field_get'] = json.loads(subprocess.check_output([str(binary), '--check-program', str(field_get)], text=True))
+ tail = '다른 길이의 문서'.encode('utf-8')
+ with serving(binary, storage, program=field_get) as writer:
+ assert rpc(writer, 'PUT', 'tail', b'tag' + struct.pack('<II', 0, 0) + tail, 0)[0] == 200
+ assert rpc(writer, 'PUT', 'bad_layout', b'short', 0)[0] == 200
+ assert rpc(writer, 'PUT', 'empty_tail', b'tag' + struct.pack('<II', 0, 0), 0)[0] == 200
+ records.append(writer.stats)
+ with serving(binary, storage, budget=len(tail), program=field_get) as reader:
+ assert rpc(reader, 'GET', 'tail')[2] == tail
+ assert rpc(reader, 'GET', 'empty_tail')[2] == b''
+ assert rpc(reader, 'GET', 'bad_layout')[0] == 413
+ assert reader.stats['peak_retained_payload_bytes'] == len(tail)
+ records.append(reader.stats)
+ checks.append('named variable tail reads use the same file version and charge only the selected suffix')
+
+ document_bytes = bytes(range(256)) * 4096
+ payload = struct.pack('<II', 16, len(document_bytes) - 32) + document_bytes
+ with serving(binary, storage, budget=len(payload), program=program) as slow:
+ with socket.create_connection(('127.0.0.1', slow.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'dynamic_slow', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == document_bytes[16:17]
+ assert rpc(slow, 'GET', 'binary')[0] == 503
+ assert response.read() == document_bytes[17:-16]
+ response.close()
+ assert rpc(slow, 'GET', 'binary')[2] == b'new'
+ assert rpc(slow, 'GET', 'dynamic_slow')[2] == document_bytes[16:-16]
+ assert slow.stats['peak_retained_payload_bytes'] == len(payload)
+ records.append(slow.stats)
+ checks.append('data-dependent response keeps and charges the original input through partial transmission')
+ return plans
+
+
+def rpc_bytes(path):
+ # CLI export is pretty JSON; wire export is compact JSON with the same model.
+ return json.dumps(json.loads(path.read_text()), ensure_ascii=False, separators=(',', ':')).encode()
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path, default=ROOT / 'build/pure-connections')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ binary = args.server.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-connections-check-') as temporary:
+ result = check(binary, Path(temporary))
+ result['binary_sha256'] = hashlib.sha256(binary.read_bytes()).hexdigest()
+ result['environment'] = {'platform': platform.platform(), 'machine': platform.machine(),
+ 'python': platform.python_version(), 'node': subprocess.check_output(['node', '--version'], text=True).strip()}
+ result['source_sha256'] = {str(path.relative_to(ROOT.parent.parent)): hashlib.sha256(path.read_bytes()).hexdigest()
+ for path in [*(ROOT / name for name in ('flow.c', 'flow.h', 'store.c', 'store.h', 'program.c', 'program.h',
+ 'server.c', 'check.py', 'test-flow.c', 'test-program.c', 'test-fields.c', 'Makefile',
+ 'examples/storage.pure', 'examples/excerpt.pure', 'examples/selection.pure', 'examples/select-text.py')),
+ *(WORKBENCH / name for name in ('remote.mjs', 'cli.mjs', 'web/core.wasm', 'web/runtime.mjs',
+ 'web/compiler.mjs', 'web/project.mjs', 'examples/direct.pure'))]}
+ output = json.dumps(result, ensure_ascii=False, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/excerpt.pure b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/excerpt.pure
new file mode 100644
index 0000000..622f9bb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/excerpt.pure
@@ -0,0 +1,13 @@
+// Read bytes 32..47 of an object that must contain the complete 64-byte window.
+// Preparation keeps the size check for 16..79, and maps only 32..47 for reply.
+on get {
+ let object = store.read(request.key);
+ let window = range(object.body, 16, 64);
+ let excerpt = range(window, 16, 16);
+ reply(object, excerpt);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/select-text.py b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/select-text.py
new file mode 100644
index 0000000..ffaf80b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/select-text.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+"""Save a UTF-8 document selection through selection.pure (character indices)."""
+import argparse
+import http.client
+import json
+from pathlib import Path
+import re
+import struct
+from urllib.parse import urlsplit
+
+LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('file', type=Path)
+ parser.add_argument('--key', required=True)
+ parser.add_argument('--start', type=int, required=True, help='first Unicode code point, starting at 0')
+ parser.add_argument('--end', type=int, required=True, help='exclusive Unicode code point boundary')
+ parser.add_argument('--revision', type=int, default=0, help='0 creates; otherwise expected stored revision')
+ parser.add_argument('--url', default='http://127.0.0.1:8767')
+ args = parser.parse_args()
+ url = urlsplit(args.url)
+ try:
+ port = url.port or 80
+ except ValueError as error:
+ parser.error(str(error))
+ if (url.scheme != 'http' or url.hostname not in ['localhost', '127.0.0.1'] or
+ url.username is not None or url.password is not None or url.path not in ['', '/'] or
+ url.query or url.fragment):
+ parser.error('use a local HTTP server origin')
+ if not re.fullmatch(r'[A-Za-z0-9_-]{1,64}', args.key) or not 0 <= args.revision <= 2**63 - 1:
+ parser.error('invalid object key or revision')
+ try:
+ with args.file.open('rb') as source:
+ document = source.read(LIMIT - 8 + 1)
+ if len(document) > LIMIT - 8:
+ parser.error('document exceeds the prototype request limit')
+ text = document.decode('utf-8')
+ except (OSError, UnicodeError) as error:
+ parser.error(str(error))
+ if not 0 <= args.start <= args.end <= len(text):
+ parser.error('selection is outside the document')
+ start = len(text[:args.start].encode('utf-8'))
+ selected = text[args.start:args.end].encode('utf-8')
+ # The boundary layout is explicit; storage receives only selected bytes.
+ payload = struct.pack('<II', start, len(selected)) + document
+ headers = {'Content-Type': 'application/octet-stream'}
+ headers['If-None-Match' if args.revision == 0 else 'If-Match'] = (
+ '*' if args.revision == 0 else f'"{args.revision}"')
+ connection = http.client.HTTPConnection(url.hostname, port, timeout=12)
+ try:
+ connection.request('PUT', '/objects/' + args.key, payload, headers)
+ response = connection.getresponse()
+ body = response.read(LIMIT + 1)
+ if response.status != 200:
+ parser.error(f'storage response {response.status}: {response.getheader("X-Pure-Error")}')
+ if body != selected:
+ parser.error('response differs from the selection; check the installed program (write may have occurred)')
+ revision = response.getheader('ETag', '')
+ if not re.fullmatch(r'"[1-9][0-9]*"', revision) or int(revision[1:-1]) > 2**63 - 1:
+ parser.error('response has no valid stored revision (write may have occurred)')
+ except (OSError, http.client.HTTPException) as error:
+ parser.error(f'{error}; storage outcome is unknown if the request was sent')
+ finally:
+ connection.close()
+ print(json.dumps({'revision': revision[1:-1], 'selected': selected.decode('utf-8'),
+ 'stored_bytes': len(selected)}, ensure_ascii=False))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/selection.pure b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/selection.pure
new file mode 100644
index 0000000..7d9d4ec
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/selection.pure
@@ -0,0 +1,19 @@
+// This is an input boundary layout, not a required storage or RAM model.
+// The client sends two little-endian u32 values followed by document bytes.
+layout Selection {
+ start: u32le;
+ count: u32le;
+ document: bytes;
+}
+
+on get {
+ let saved = store.read(request.key);
+ reply(saved, saved.body);
+}
+
+on put {
+ let input = view(Selection, request.body);
+ let selected = range(input.document, input.start, input.count);
+ let saved = store.write(request.key, request.revision, selected);
+ reply(saved, selected);
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/storage.pure b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/storage.pure
new file mode 100644
index 0000000..ff54ea3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/examples/storage.pure
@@ -0,0 +1,11 @@
+// The host supplies request bytes, an object name, and the expected revision.
+// Failed storage results propagate to the host's response without executing reply.
+on get {
+ let object = store.read(request.key);
+ reply(object, object.body);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/flow.c b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/flow.c
new file mode 100644
index 0000000..1070c70
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/flow.c
@@ -0,0 +1,41 @@
+#include "flow.h"
+#include <assert.h>
+
+void pure_transfer_abort(PureTransfer *t) {
+ if (!t->active) return;
+ PureRelease release = t->release;
+ void *owner = t->owner;
+ *t = (PureTransfer){0};
+ if (release) release(owner);
+}
+
+static void advance(PureTransfer *t) {
+ while (t->active && t->part < 2 && t->offset == t->spans[t->part].size) {
+ t->part++;
+ t->offset = 0;
+ }
+ if (t->active && t->part == 2) pure_transfer_abort(t);
+}
+
+void pure_transfer_init(PureTransfer *t, PureSpan header, PureSpan body,
+ void *owner, PureRelease release) {
+ assert(!t->active);
+ assert((!header.size || header.data) && (!body.size || body.data));
+ *t = (PureTransfer){.spans = {header, body}, .owner = owner,
+ .release = release, .active = true};
+ advance(t);
+}
+
+PureSpan pure_transfer_next(const PureTransfer *t, size_t limit) {
+ if (!t->active) return (PureSpan){0};
+ PureSpan span = t->spans[t->part];
+ size_t remaining = span.size - t->offset;
+ return (PureSpan){span.data + t->offset, remaining < limit ? remaining : limit};
+}
+
+bool pure_transfer_consume(PureTransfer *t, size_t bytes) {
+ if (!t->active || bytes > t->spans[t->part].size - t->offset) return false;
+ t->offset += bytes;
+ advance(t);
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/flow.h b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/flow.h
new file mode 100644
index 0000000..6e27c58
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/flow.h
@@ -0,0 +1,25 @@
+#ifndef PURE_FLOW_H
+#define PURE_FLOW_H
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef struct { const unsigned char *data; size_t size; } PureSpan;
+typedef void (*PureRelease)(void *owner);
+
+/* A borrowed body stays alive until every byte is consumed or the transfer is
+ * aborted. A successful send() consumes bytes; peer receipt is a separate fact.
+ * Single owner thread; callbacks must not reenter or reuse this transfer. */
+typedef struct {
+ PureSpan spans[2];
+ size_t part, offset;
+ void *owner;
+ PureRelease release;
+ bool active;
+} PureTransfer;
+
+void pure_transfer_init(PureTransfer *, PureSpan header, PureSpan body,
+ void *owner, PureRelease);
+PureSpan pure_transfer_next(const PureTransfer *, size_t limit);
+bool pure_transfer_consume(PureTransfer *, size_t bytes);
+void pure_transfer_abort(PureTransfer *);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/program.c b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/program.c
new file mode 100644
index 0000000..a01bb7c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/program.c
@@ -0,0 +1,402 @@
+#include "program.h"
+#include "store.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+enum { NAME = 256, NUMBER, SYMBOLS = 32, LAYOUTS = 4, FIELDS = 16 };
+typedef enum { BYTE_VALUE, RESULT_VALUE, LAYOUT_VALUE, INDEX_VALUE } ValueKind;
+typedef struct {
+ char name[32];
+ ValueKind kind;
+ PureRegion region;
+ size_t step, layout;
+ PureIndex index;
+} Symbol;
+typedef struct {
+ char name[32];
+ size_t offset, length;
+ bool number, tail;
+} Field;
+typedef struct {
+ char name[32];
+ Field fields[FIELDS];
+ size_t count, prefix;
+ bool tail;
+} Layout;
+typedef struct {
+ const char *source;
+ size_t length, at, line, token_line;
+ int token;
+ char name[32];
+ size_t number;
+ char *error;
+ size_t error_size;
+ bool failed, put, effect;
+ Symbol symbols[SYMBOLS];
+ size_t count, layout_count;
+ Layout layouts[LAYOUTS];
+ PureProgram program;
+} Parser;
+
+static bool reject(Parser *p, const char *message) {
+ if (!p->failed && p->error_size) snprintf(p->error, p->error_size, "line %zu: %s", p->token_line, message);
+ p->failed = true;
+ return false;
+}
+
+static bool letter(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
+}
+
+static bool next(Parser *p) {
+ while (p->at < p->length) {
+ char c = p->source[p->at];
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ if (c == '\n') ++p->line;
+ ++p->at;
+ } else if (c == '/' && p->at + 1 < p->length && p->source[p->at + 1] == '/') {
+ while (p->at < p->length && p->source[p->at] != '\n') ++p->at;
+ } else break;
+ }
+ p->token_line = p->line;
+ p->name[0] = 0;
+ p->token = 0;
+ if (p->at == p->length) return true;
+ char c = p->source[p->at++];
+ if (letter(c)) {
+ size_t start = p->at - 1;
+ while (p->at < p->length && (letter(p->source[p->at]) ||
+ (p->source[p->at] >= '0' && p->source[p->at] <= '9'))) ++p->at;
+ size_t size = p->at - start;
+ if (size >= sizeof(p->name)) return reject(p, "name exceeds 31 bytes");
+ memcpy(p->name, p->source + start, size);
+ p->name[size] = 0;
+ p->token = NAME;
+ } else if (c >= '0' && c <= '9') {
+ size_t value = (size_t)(c - '0');
+ while (p->at < p->length && p->source[p->at] >= '0' && p->source[p->at] <= '9') {
+ unsigned digit = (unsigned)(p->source[p->at++] - '0');
+ if (value > (SIZE_MAX - digit) / 10) return reject(p, "integer overflow");
+ value = value * 10 + digit;
+ }
+ p->number = value;
+ p->token = NUMBER;
+ } else if (c && strchr("{}().,=;:[]", c)) p->token = (unsigned char)c;
+ else return reject(p, "unexpected character");
+ return true;
+}
+
+static bool is_word(Parser *p, const char *word) {
+ return p->token == NAME && !strcmp(p->name, word);
+}
+
+static bool word(Parser *p, const char *expected) {
+ return is_word(p, expected) ? next(p) : reject(p, expected);
+}
+
+static bool token(Parser *p, int expected) {
+ return p->token == expected ? next(p) : reject(p, "unexpected token");
+}
+
+static Symbol *find(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->count; ++i)
+ if (!strcmp(name, p->symbols[i].name)) return &p->symbols[i];
+ return NULL;
+}
+
+static bool field(Parser *p, const char *object, const char *name) {
+ return word(p, object) && token(p, '.') && word(p, name);
+}
+
+static bool require_bytes(Parser *p, const Symbol *value) {
+ return value->kind == BYTE_VALUE || reject(p, "expected bytes; select a byte field");
+}
+
+static void require_length(Parser *p, size_t required) {
+ size_t *minimum = p->put ? &p->program.input_required : &p->program.read_required;
+ if (required > *minimum) *minimum = required;
+}
+
+static Layout *find_layout(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->layout_count; ++i)
+ if (!strcmp(name, p->layouts[i].name)) return &p->layouts[i];
+ return NULL;
+}
+
+static bool layout_definition(Parser *p) {
+ if (p->layout_count == LAYOUTS) return reject(p, "program exceeds 4 layouts");
+ if (!next(p)) return false;
+ if (p->token != NAME || find_layout(p, p->name)) return reject(p, "expected a unique layout name");
+ Layout *layout = &p->layouts[p->layout_count];
+ strcpy(layout->name, p->name);
+ if (!next(p) || !token(p, '{')) return false;
+ while (p->token != '}') {
+ if (layout->count == FIELDS) return reject(p, "layout exceeds 16 fields");
+ if (layout->tail) return reject(p, "variable bytes must be the last field");
+ if (p->token != NAME) return reject(p, "expected a field name");
+ for (size_t i = 0; i < layout->count; ++i)
+ if (!strcmp(layout->fields[i].name, p->name)) return reject(p, "duplicate field");
+ Field *f = &layout->fields[layout->count];
+ strcpy(f->name, p->name);
+ f->offset = layout->prefix;
+ if (!next(p) || !token(p, ':')) return false;
+ if (is_word(p, "u32le")) {
+ f->number = true;
+ f->length = 4;
+ if (!next(p)) return false;
+ } else if (is_word(p, "bytes")) {
+ if (!next(p)) return false;
+ if (p->token == '[') {
+ if (!next(p)) return false;
+ if (p->token != NUMBER) return reject(p, "fixed bytes requires a constant size");
+ f->length = p->number;
+ if (!next(p) || !token(p, ']')) return false;
+ } else { f->tail = true; layout->tail = true; }
+ } else return reject(p, "supported field types: u32le, bytes[N], bytes");
+ if (f->length > PURE_OBJECT_LIMIT - layout->prefix) return reject(p, "layout exceeds object bound");
+ layout->prefix += f->length;
+ ++layout->count;
+ if (!token(p, ';')) return false;
+ }
+ if (!layout->count) return reject(p, "empty layout");
+ ++p->layout_count;
+ return token(p, '}');
+}
+
+static bool reference(Parser *p, Symbol *out) {
+ if (is_word(p, "request")) {
+ if (!p->put) return reject(p, "request.body is only available in on put");
+ *out = (Symbol){.kind = BYTE_VALUE, .region = {.to_end = true}};
+ return field(p, "request", "body");
+ }
+ Symbol *symbol = p->token == NAME ? find(p, p->name) : NULL;
+ if (!symbol) return reject(p, "unknown value");
+ *out = *symbol;
+ if (!next(p)) return false;
+ if (p->token != '.') return true;
+ if (!next(p)) return false;
+ if (symbol->kind == RESULT_VALUE) {
+ if (p->put) return reject(p, "write result has no body; use the input value");
+ *out = (Symbol){.kind = BYTE_VALUE, .region = {.to_end = true}};
+ return word(p, "body");
+ }
+ if (symbol->kind != LAYOUT_VALUE || p->token != NAME) return reject(p, "expected a layout field");
+ Layout *layout = &p->layouts[symbol->layout];
+ Field *f = NULL;
+ for (size_t i = 0; i < layout->count; ++i)
+ if (!strcmp(p->name, layout->fields[i].name)) f = &layout->fields[i];
+ if (!f) return reject(p, "unknown layout field");
+ size_t offset = symbol->region.offset + f->offset;
+ *out = (Symbol){.kind = f->number ? INDEX_VALUE : BYTE_VALUE};
+ if (f->number) out->index = (PureIndex){.value = offset, .from_u32le = true};
+ else out->region = (PureRegion){.offset = offset,
+ .length = f->tail ? (symbol->region.to_end ? 0 : symbol->region.length - f->offset) : f->length,
+ .to_end = f->tail && symbol->region.to_end};
+ return next(p);
+}
+
+static bool byte_reference(Parser *p, Symbol *out) {
+ return reference(p, out) && require_bytes(p, out);
+}
+
+static bool index_value(Parser *p, PureIndex *out) {
+ if (p->token == NUMBER) {
+ *out = (PureIndex){.value = p->number};
+ return next(p);
+ }
+ Symbol value;
+ if (!reference(p, &value)) return false;
+ if (value.kind != INDEX_VALUE) return reject(p, "range requires an integer or u32le field");
+ *out = value.index;
+ return true;
+}
+
+static bool layout_view(Parser *p, Symbol *out) {
+ if (!next(p) || !token(p, '(')) return false;
+ Layout *layout = p->token == NAME ? find_layout(p, p->name) : NULL;
+ if (!layout) return reject(p, "unknown layout");
+ if (!next(p) || !token(p, ',')) return false;
+ Symbol source;
+ if (!byte_reference(p, &source) || !token(p, ')')) return false;
+ if (source.step) return reject(p, "layout view requires a statically located source");
+ size_t bound = source.region.to_end ? PURE_OBJECT_LIMIT - source.region.offset : source.region.length;
+ if (layout->prefix > bound) return reject(p, "layout exceeds source bound");
+ require_length(p, source.region.offset + layout->prefix);
+ *out = (Symbol){.kind = LAYOUT_VALUE, .region = source.region, .layout = (size_t)(layout - p->layouts)};
+ if (!layout->tail) { out->region.length = layout->prefix; out->region.to_end = false; }
+ return true;
+}
+
+static bool view(Parser *p, Symbol *out) {
+ if (is_word(p, "view")) return layout_view(p, out);
+ if (!is_word(p, "range")) return reference(p, out);
+ Symbol parent;
+ PureIndex offset, length;
+ if (!next(p) || !token(p, '(') || !byte_reference(p, &parent) || !token(p, ',') ||
+ !index_value(p, &offset) || !token(p, ',') || !index_value(p, &length) || !token(p, ')')) return false;
+ bool dynamic = parent.step || offset.from_u32le || length.from_u32le;
+ *out = (Symbol){.kind = BYTE_VALUE};
+ if (dynamic) {
+ if (!p->put) return reject(p, "data-dependent ranges currently require PUT input");
+ if (p->program.input_steps == PURE_DYNAMIC_LIMIT) return reject(p, "input exceeds 8 dynamic ranges");
+ if ((!offset.from_u32le && offset.value > PURE_OBJECT_LIMIT) ||
+ (!length.from_u32le && length.value > PURE_OBJECT_LIMIT)) return reject(p, "range exceeds object bound");
+ PureRangeStep *step = &p->program.steps[p->program.input_steps++];
+ *step = (PureRangeStep){.source = parent.region, .source_step = parent.step,
+ .offset = offset, .length = length};
+ out->step = p->program.input_steps;
+ } else {
+ size_t bound = parent.region.to_end ? PURE_OBJECT_LIMIT - parent.region.offset : parent.region.length;
+ if (offset.value > bound || length.value > bound - offset.value) return reject(p, "range exceeds its source bound");
+ out->region = (PureRegion){.offset = parent.region.offset + offset.value, .length = length.value};
+ require_length(p, out->region.offset + out->region.length);
+ }
+ ++p->program.range_definitions;
+ return true;
+}
+
+static bool effect(Parser *p, Symbol *out) {
+ if (p->effect) return reject(p, "only one storage effect is supported per handler");
+ if (!word(p, "store") || !token(p, '.') || !word(p, p->put ? "write" : "read") ||
+ !token(p, '(') || !field(p, "request", "key")) return false;
+ if (p->put) {
+ Symbol value;
+ if (!token(p, ',') || !field(p, "request", "revision") || !token(p, ',') ||
+ !byte_reference(p, &value)) return false;
+ p->program.write = value.region;
+ p->program.write_step = value.step;
+ }
+ if (!token(p, ')')) return false;
+ out->kind = RESULT_VALUE;
+ p->effect = true;
+ return true;
+}
+
+static bool handler(Parser *p) {
+ p->count = 0;
+ p->effect = false;
+ if (!token(p, '{')) return false;
+ while (is_word(p, "let")) {
+ if (p->put && p->effect) return reject(p, "all views must precede store.write; reply must follow it");
+ if (p->count == SYMBOLS) return reject(p, "handler exceeds 32 definitions");
+ if (!next(p)) return false;
+ if (p->token != NAME || is_word(p, "request") || is_word(p, "store") ||
+ is_word(p, "range") || is_word(p, "view")) return reject(p, "expected a non-reserved definition name");
+ if (find(p, p->name)) return reject(p, "duplicate definition");
+ char name[32];
+ strcpy(name, p->name);
+ Symbol symbol = {0};
+ if (!next(p) || !token(p, '=')) return false;
+ if (is_word(p, "store")) {
+ if (!effect(p, &symbol)) return false;
+ } else {
+ if (!view(p, &symbol)) return false;
+ ++p->program.view_definitions;
+ }
+ if (!token(p, ';')) return false;
+ strcpy(symbol.name, name);
+ p->symbols[p->count++] = symbol;
+ }
+ if (!p->effect) return reject(p, "handler requires its storage effect");
+ if (!word(p, "reply") || !token(p, '(')) return false;
+ Symbol *result = p->token == NAME ? find(p, p->name) : NULL;
+ if (!result || result->kind != RESULT_VALUE) return reject(p, "reply requires this handler's storage result");
+ if (!next(p)) return false;
+ Symbol body = {0};
+ bool has_body = p->token == ',';
+ if (has_body && (!next(p) || !byte_reference(p, &body))) return false;
+ if (!token(p, ')') || !token(p, ';') || !token(p, '}')) return false;
+ if (p->put) {
+ p->program.reply = body.region;
+ p->program.reply_step = body.step;
+ p->program.reply_input = has_body;
+ } else p->program.read = body.region;
+ return true;
+}
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size) {
+ Parser p = {.source = source, .length = length, .line = 1, .token_line = 1,
+ .error = error, .error_size = error_size};
+ if (error_size) error[0] = 0;
+ if (length > PURE_PROGRAM_LIMIT) return reject(&p, "program exceeds 16 KiB");
+ if (!next(&p)) return false;
+ while (is_word(&p, "layout")) if (!layout_definition(&p)) return false;
+ unsigned handlers = 0;
+ while (p.token) {
+ if (!word(&p, "on")) return false;
+ if (!is_word(&p, "get") && !is_word(&p, "put")) return reject(&p, "expected get or put handler");
+ p.put = is_word(&p, "put");
+ unsigned bit = p.put ? 2 : 1;
+ if (handlers & bit) return reject(&p, "duplicate handler");
+ handlers |= bit;
+ if (!next(&p) || !handler(&p)) return false;
+ }
+ if (handlers != 3) return reject(&p, "both get and put handlers are required");
+ *out = p.program; /* Invalid preparation never changes the installed plan. */
+ return true;
+}
+
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size) {
+ FILE *file = fopen(path, "rb");
+ if (!file) {
+ if (error_size) snprintf(error, error_size, "cannot open program");
+ return false;
+ }
+ char source[PURE_PROGRAM_LIMIT + 1];
+ size_t length = fread(source, 1, sizeof(source), file);
+ bool bad = ferror(file) != 0;
+ if (fclose(file)) bad = true;
+ if (bad) {
+ if (error_size) snprintf(error, error_size, "cannot read program");
+ return false;
+ }
+ return pure_program_parse(source, length, out, error, error_size);
+}
+
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out) {
+ *out = (PureSpan){0};
+ if (region.offset > source.size) return false;
+ size_t length = region.to_end ? source.size - region.offset : region.length;
+ if (length > source.size - region.offset) return false;
+ *out = (PureSpan){length ? source.data + region.offset : NULL, length};
+ return true;
+}
+
+static bool index_read(PureIndex index, PureSpan source, size_t *out) {
+ if (!index.from_u32le) { *out = index.value; return true; }
+ if (index.value > source.size || 4 > source.size - index.value) return false;
+ const unsigned char *bytes = source.data + index.value;
+ *out = (size_t)bytes[0] | (size_t)bytes[1] << 8 | (size_t)bytes[2] << 16 | (size_t)bytes[3] << 24;
+ return true;
+}
+
+static bool resolve(PureRegion region, size_t step, PureSpan source,
+ const PureSpan *values, size_t count, PureSpan *out) {
+ if (!step) return pure_region_span(region, source, out);
+ if (step > count) return false;
+ *out = values[step - 1];
+ return true;
+}
+
+bool pure_program_input(const PureProgram *p, PureSpan source, PureSpan *write, PureSpan *reply) {
+ *write = (PureSpan){0};
+ *reply = (PureSpan){0};
+ if (source.size < p->input_required || p->input_steps > PURE_DYNAMIC_LIMIT) return false;
+ PureSpan values[PURE_DYNAMIC_LIMIT];
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ PureSpan parent;
+ size_t offset, length;
+ if (!resolve(step->source, step->source_step, source, values, i, &parent) ||
+ !index_read(step->offset, source, &offset) || !index_read(step->length, source, &length) ||
+ !pure_region_span((PureRegion){.offset = offset, .length = length}, parent, &values[i])) return false;
+ }
+ PureSpan stored, returned = {0};
+ if (!resolve(p->write, p->write_step, source, values, p->input_steps, &stored) ||
+ (p->reply_input && !resolve(p->reply, p->reply_step, source, values, p->input_steps, &returned))) return false;
+ *write = stored;
+ *reply = returned;
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/program.h b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/program.h
new file mode 100644
index 0000000..f2b5b2f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/program.h
@@ -0,0 +1,39 @@
+#ifndef PURE_PROGRAM_H
+#define PURE_PROGRAM_H
+#include "flow.h"
+
+#define PURE_PROGRAM_LIMIT 16384u
+#define PURE_DYNAMIC_LIMIT 8u
+typedef struct {
+ size_t offset, length;
+ bool to_end;
+} PureRegion;
+
+typedef struct { size_t value; bool from_u32le; } PureIndex;
+typedef struct {
+ PureRegion source;
+ size_t source_step; /* 0: source region; otherwise a preceding step + 1. */
+ PureIndex offset, length;
+} PureRangeStep;
+
+/* Prepared connections, not an instruction stream. All view definitions are
+ * checked at preparation; their root-length requirements survive elimination.
+ * Input views are evaluated before the write effect. A read still opens and
+ * validates the object even if its response has no body. */
+typedef struct {
+ PureRegion read, write, reply;
+ size_t read_required, input_required;
+ size_t view_definitions, range_definitions;
+ size_t write_step, reply_step, input_steps;
+ PureRangeStep steps[PURE_DYNAMIC_LIMIT];
+ bool reply_input;
+} PureProgram;
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size);
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size);
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out);
+/* Validates all input views, including unused dynamic views, before any effect.
+ * Returns borrowed selections; their lifetime remains that of source. */
+bool pure_program_input(const PureProgram *, PureSpan source, PureSpan *write, PureSpan *reply);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/server.c b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/server.c
new file mode 100644
index 0000000..e4e5b88
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/server.c
@@ -0,0 +1,393 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include "program.h"
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+enum { SLOTS = 8, HEADER_LIMIT = 4096, CHUNK = 65536 };
+typedef enum { READING_HEADER, READING_BODY, WRITING } Phase;
+typedef struct Server Server;
+typedef struct {
+ int fd;
+ Phase phase;
+ uint64_t deadline;
+ char request[HEADER_LIMIT + 1], response[512], key[65];
+ size_t header_size, body_size, received, charged;
+ unsigned char *body;
+ bool put;
+ int64_t expected;
+ PureStoredView stored;
+ PureTransfer transfer;
+ Server *server;
+} Connection;
+struct Server {
+ const char *path;
+ PureProgram program;
+ size_t budget, retained, peak_retained, active, peak_active;
+ uint64_t accepted, commits, gets, conflicts, budget_rejections, expired;
+ uint64_t releases, prefix_copy_bytes, borrowed_output_bytes;
+ uint64_t timeout_ms;
+ int send_buffer;
+ Connection connections[SLOTS];
+};
+static volatile sig_atomic_t stopping;
+static void stop_server(int sig) { (void)sig; stopping = 1; }
+
+static uint64_t now_ms(void) {
+ struct timespec t;
+ if (clock_gettime(CLOCK_MONOTONIC, &t)) abort();
+ return (uint64_t)t.tv_sec * 1000 + (uint64_t)t.tv_nsec / 1000000;
+}
+
+static bool number(const char *text, uint64_t maximum, uint64_t *value) {
+ if (!*text) return false;
+ uint64_t n = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > maximum || n > (maximum - digit) / 10) return false;
+ n = n * 10 + digit;
+ }
+ *value = n;
+ return true;
+}
+
+static void release_payload(void *owner) {
+ Connection *c = owner;
+ bool owned = c->body || c->stored.mapped_size || c->charged;
+ pure_store_release(&c->stored);
+ free(c->body);
+ c->body = NULL;
+ assert(c->charged <= c->server->retained);
+ c->server->retained -= c->charged;
+ c->charged = 0;
+ if (owned) ++c->server->releases;
+}
+
+static void close_connection(Connection *c) {
+ if (c->fd < 0) return;
+ if (c->transfer.active) pure_transfer_abort(&c->transfer);
+ else if (c->body || c->stored.mapped_size || c->charged) release_payload(c);
+ close(c->fd);
+ --c->server->active;
+ *c = (Connection){.fd = -1};
+}
+
+static bool charge(Connection *c, size_t size) {
+ Server *s = c->server;
+ if (size > s->budget - s->retained) { ++s->budget_rejections; return false; }
+ s->retained += size;
+ c->charged += size;
+ if (s->retained > s->peak_retained) s->peak_retained = s->retained;
+ return true;
+}
+
+static void respond(Connection *c, int status, const char *reason, const char *error,
+ int64_t revision, PureSpan body) {
+ char tag[80] = "";
+ if (revision > 0) snprintf(tag, sizeof(tag), "ETag: \"%" PRId64 "\"\r\n", revision);
+ int length = snprintf(c->response, sizeof(c->response),
+ "HTTP/1.1 %d %s\r\nContent-Length: %zu\r\nConnection: close\r\n"
+ "Content-Type: application/octet-stream\r\nCache-Control: no-store\r\n"
+ "X-Pure-Error: %s\r\n%s\r\n", status, reason, body.size, error, tag);
+ assert(length > 0 && (size_t)length < sizeof(c->response));
+ c->phase = WRITING;
+ pure_transfer_init(&c->transfer,
+ (PureSpan){(const unsigned char *)c->response, (size_t)length}, body, c, release_payload);
+}
+
+static void fail(Connection *c, int status, const char *reason, const char *error) {
+ /* No outstanding backend access on the owner thread at this point. */
+ if (c->body || c->stored.mapped_size || c->charged) release_payload(c);
+ respond(c, status, reason, error, 0, (PureSpan){0});
+}
+
+static void run_request(Connection *c) {
+ PureResult result;
+ int64_t revision = 0;
+ PureProgram *program = &c->server->program;
+ PureSpan output = {0};
+ if (c->put) {
+ PureSpan source = {c->body, c->body_size}, value;
+ /* Validate every authored view before performing an external effect,
+ * including unused views. Static preparation preserves these guards. */
+ if (!pure_program_input(program, source, &value, &output)) {
+ fail(c, 413, "Content Too Large", "limit");
+ return;
+ }
+ result = pure_store_put(c->server->path, c->key, c->expected, value, &revision);
+ /* A reply can consume the same input. Its owner lives until transfer
+ * completion; otherwise storage completion ends the input lifetime. */
+ if (result != PURE_OK || !output.size) { release_payload(c); output = (PureSpan){0}; }
+ if (result == PURE_OK) {
+ ++c->server->commits;
+ c->server->borrowed_output_bytes += output.size;
+ }
+ } else {
+ result = pure_store_select(c->server->path, c->key, program->read.offset,
+ program->read.length, program->read.to_end, program->read_required,
+ c->server->budget - c->server->retained, &c->stored);
+ if (result == PURE_OK) {
+ if (!charge(c, c->stored.body.size)) abort(); /* Same owner thread. */
+ revision = c->stored.revision;
+ output = c->stored.body;
+ ++c->server->gets;
+ c->server->borrowed_output_bytes += c->stored.body.size;
+ } else if (result == PURE_BUDGET) ++c->server->budget_rejections;
+ }
+ switch (result) {
+ case PURE_OK: respond(c, 200, "OK", "none", revision, output); break;
+ case PURE_NOT_FOUND: fail(c, 404, "Not Found", "not_found"); break;
+ case PURE_CONFLICT:
+ ++c->server->conflicts;
+ respond(c, 412, "Precondition Failed", "conflict", revision, (PureSpan){0}); break;
+ case PURE_BUSY: fail(c, 503, "Service Unavailable", "store_busy"); break;
+ case PURE_BUDGET: fail(c, 503, "Service Unavailable", "payload_budget"); break;
+ case PURE_LIMIT: fail(c, 413, "Content Too Large", "limit"); break;
+ case PURE_UNCERTAIN: fail(c, 500, "Internal Server Error", "durability_unknown"); break;
+ default: fail(c, 500, "Internal Server Error", "storage"); break;
+ }
+}
+
+/* Deliberately bounded HTTP/1.1 subset: one GET/PUT, Content-Length, close.
+ * No transfer coding, pipelining, trailers, Expect, URL decoding, or proxying. */
+static bool parse_header(Connection *c, size_t end) {
+ for (size_t i = 0; i < end; ++i) {
+ unsigned char b = (unsigned char)c->request[i];
+ if ((b < 32 && b != '\r' && b != '\n' && b != '\t') || b == 127) return false;
+ }
+ char *line = c->request, *next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *path = strchr(line, ' ');
+ if (!path) return false;
+ *path++ = 0;
+ if (strcmp(line, "PUT") == 0) c->put = true;
+ else if (strcmp(line, "GET") != 0) return false;
+ char *version = strchr(path, ' ');
+ if (!version) return false;
+ *version++ = 0;
+ if (strcmp(version, "HTTP/1.1") || strncmp(path, "/objects/", 9)) return false;
+ const char *key = path + 9;
+ size_t key_size = strlen(key);
+ if (!key_size || key_size > 64) return false;
+ for (size_t i = 0; i < key_size; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ memcpy(c->key, key, key_size + 1);
+ bool length_seen = false, condition_seen = false, host_seen = false;
+ line = next + 2;
+ while (*line != '\r') {
+ next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *value = strchr(line, ':');
+ if (!value || value == line) return false;
+ *value++ = 0;
+ for (char *p = line; *p; ++p)
+ if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') || *p == '-')) return false;
+ while (*value == ' ' || *value == '\t') ++value;
+ char *tail = value + strlen(value);
+ while (tail > value && (tail[-1] == ' ' || tail[-1] == '\t')) *--tail = 0;
+ if (strchr(value, '\r') || strchr(value, '\n')) return false;
+ uint64_t n;
+ if (!strcasecmp(line, "Content-Length")) {
+ if (length_seen || !number(value, SIZE_MAX, &n)) return false;
+ length_seen = true;
+ c->body_size = (size_t)n;
+ } else if (!strcasecmp(line, "Host")) {
+ if (host_seen || !*value) return false;
+ host_seen = true;
+ } else if (!strcasecmp(line, "If-Match")) {
+ if (condition_seen || tail - value < 3 || *value != '"' || tail[-1] != '"') return false;
+ tail[-1] = 0;
+ if (!number(value + 1, INT64_MAX, &n) || !n) return false;
+ c->expected = (int64_t)n;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "If-None-Match")) {
+ if (condition_seen || strcmp(value, "*")) return false;
+ c->expected = 0;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "Transfer-Encoding") || !strcasecmp(line, "Expect")) return false;
+ line = next + 2;
+ }
+ return host_seen && (c->put ? length_seen && condition_seen : !condition_seen && c->body_size == 0);
+}
+
+static void read_connection(Connection *c) {
+ if (c->phase == READING_HEADER) {
+ ssize_t n = recv(c->fd, c->request + c->header_size, HEADER_LIMIT - c->header_size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->header_size += (size_t)n;
+ c->request[c->header_size] = 0;
+ /* Scan by byte count, so embedded NUL cannot hide a terminator. */
+ size_t end = 0;
+ for (size_t i = 3; i < c->header_size; ++i)
+ if (!memcmp(c->request + i - 3, "\r\n\r\n", 4)) { end = i + 1; break; }
+ if (!end) {
+ if (c->header_size == HEADER_LIMIT) fail(c, 431, "Request Header Fields Too Large", "headers");
+ return;
+ }
+ size_t prefix = c->header_size - end;
+ if (!parse_header(c, end)) { fail(c, 400, "Bad Request", "request"); return; }
+ if (c->body_size > PURE_OBJECT_LIMIT) { fail(c, 413, "Content Too Large", "limit"); return; }
+ if (prefix > c->body_size) { fail(c, 400, "Bad Request", "extra_body"); return; }
+ if (!c->put) { run_request(c); return; }
+ if (!charge(c, c->body_size)) { fail(c, 503, "Service Unavailable", "payload_budget"); return; }
+ c->body = malloc(c->body_size ? c->body_size : 1);
+ if (!c->body) { fail(c, 503, "Service Unavailable", "allocation"); return; }
+ if (prefix) memcpy(c->body, c->request + end, prefix);
+ c->server->prefix_copy_bytes += prefix;
+ c->received = prefix;
+ c->phase = READING_BODY;
+ if (c->received == c->body_size) run_request(c);
+ } else {
+ size_t remaining = c->body_size - c->received;
+ ssize_t n = recv(c->fd, c->body + c->received, remaining < CHUNK ? remaining : CHUNK, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->received += (size_t)n;
+ if (c->received == c->body_size) run_request(c);
+ }
+}
+
+static void write_connection(Connection *c) {
+ PureSpan span = pure_transfer_next(&c->transfer, CHUNK);
+ ssize_t n = send(c->fd, span.data, span.size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ if (!pure_transfer_consume(&c->transfer, (size_t)n)) abort();
+ if (!c->transfer.active) close_connection(c);
+}
+
+static bool nonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
+}
+
+int main(int argc, char **argv) {
+ Server server = {.budget = 4u * 1024u * 1024u, .timeout_ms = 10000};
+ unsigned port = 8767;
+ const char *program_path = NULL;
+ bool explain = argc == 3 && !strcmp(argv[1], "--check-program");
+ char program_error[160];
+ if (explain) program_path = argv[2];
+ for (int i = 1; !explain && i < argc; i += 2) {
+ if (i + 1 == argc) goto usage;
+ uint64_t value;
+ if (!strcmp(argv[i], "--store")) server.path = argv[i + 1];
+ else if (!strcmp(argv[i], "--program")) program_path = argv[i + 1];
+ else if (!strcmp(argv[i], "--port") && number(argv[i + 1], 65535, &value)) port = (unsigned)value;
+ else if (!strcmp(argv[i], "--budget") && number(argv[i + 1], SIZE_MAX, &value) && value) server.budget = (size_t)value;
+ else if (!strcmp(argv[i], "--timeout-ms") && number(argv[i + 1], 3600000, &value) && value) server.timeout_ms = value;
+ else if (!strcmp(argv[i], "--send-buffer") && number(argv[i + 1], INT32_MAX, &value)) server.send_buffer = (int)value;
+ else goto usage;
+ }
+ if (!program_path || (!explain && !server.path)) goto usage;
+ if (!pure_program_load(program_path, &server.program, program_error, sizeof(program_error))) {
+ fprintf(stderr, "Program: %s\n", program_error); return 2;
+ }
+ if (explain) {
+ PureProgram *p = &server.program;
+ printf("{\"read\":{\"to_end\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"write\":{\"to_end\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"reply_input\":%s,\"view_definitions\":%zu,\"range_definitions\":%zu,"
+ "\"runtime_view_steps\":%zu,\"write_step\":%zu,\"reply_step\":%zu,\"prepared_program_bytes\":%zu,\"steps\":[",
+ p->read.to_end ? "true" : "false", p->read.offset, p->read.length, p->read_required,
+ p->write.to_end ? "true" : "false", p->write.offset, p->write.length, p->input_required,
+ p->reply_input ? "true" : "false", p->view_definitions, p->range_definitions,
+ p->input_steps, p->write_step, p->reply_step, sizeof(*p));
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ printf("%s{\"source_step\":%zu,\"source\":{\"offset\":%zu,\"length\":%zu,\"to_end\":%s},"
+ "\"offset\":{\"value\":%zu,\"from_u32le\":%s},\"length\":{\"value\":%zu,\"from_u32le\":%s}}",
+ i ? "," : "", step->source_step, step->source.offset, step->source.length,
+ step->source.to_end ? "true" : "false", step->offset.value, step->offset.from_u32le ? "true" : "false",
+ step->length.value, step->length.from_u32le ? "true" : "false");
+ }
+ puts("]}");
+ return 0;
+ }
+ if (pure_store_init(server.path) != PURE_OK) { fputs("Cannot initialize byte store directory\n", stderr); return 1; }
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, stop_server);
+ signal(SIGTERM, stop_server);
+ int listener = socket(AF_INET, SOCK_STREAM, 0);
+ if (listener < 0) { perror("socket"); return 1; }
+ int one = 1;
+ setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ struct sockaddr_in address = {.sin_family = AF_INET, .sin_port = htons((uint16_t)port),
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ if (bind(listener, (struct sockaddr *)&address, sizeof(address)) || listen(listener, SLOTS) || !nonblocking(listener)) {
+ perror("listen"); close(listener); return 1;
+ }
+ socklen_t address_size = sizeof(address);
+ if (getsockname(listener, (struct sockaddr *)&address, &address_size)) { close(listener); return 1; }
+ for (size_t i = 0; i < SLOTS; ++i) server.connections[i].fd = -1;
+ printf("{\"port\":%u,\"storage\":\"immutable-byte-extents-v1\"}\n", ntohs(address.sin_port));
+ fflush(stdout);
+ while (!stopping) {
+ struct pollfd polls[SLOTS + 1] = {{.fd = server.active < SLOTS ? listener : -1, .events = POLLIN}};
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ polls[i + 1] = (struct pollfd){.fd = c->fd, .events = c->phase == WRITING ? POLLOUT : POLLIN};
+ }
+ int ready = poll(polls, SLOTS + 1, 50);
+ if (ready < 0 && errno != EINTR) { perror("poll"); stopping = 1; }
+ uint64_t now = now_ms();
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ if (c->fd < 0) continue;
+ if (now >= c->deadline) { ++server.expired; close_connection(c); continue; }
+ short events = polls[i + 1].revents;
+ if (events & (POLLERR | POLLNVAL)) { close_connection(c); continue; }
+ if (events & (POLLIN | POLLOUT | POLLHUP)) {
+ if (c->phase == WRITING) write_connection(c); else read_connection(c);
+ }
+ }
+ if (!stopping && (polls[0].revents & POLLIN)) {
+ int fd = accept(listener, NULL, NULL);
+ if (fd < 0) continue;
+ if (!nonblocking(fd)) { close(fd); continue; }
+ if (server.send_buffer) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &server.send_buffer, sizeof(server.send_buffer));
+ for (size_t i = 0; i < SLOTS; ++i) if (server.connections[i].fd < 0) {
+ server.connections[i] = (Connection){.fd = fd, .server = &server, .deadline = now_ms() + server.timeout_ms};
+ ++server.active;
+ ++server.accepted;
+ if (server.active > server.peak_active) server.peak_active = server.active;
+ break;
+ }
+ }
+ }
+ close(listener);
+ for (size_t i = 0; i < SLOTS; ++i) close_connection(&server.connections[i]);
+ fprintf(stderr, "{\"active\":%zu,\"retained_payload_bytes\":%zu,\"peak_retained_payload_bytes\":%zu,"
+ "\"payload_budget\":%zu,\"peak_connections\":%zu,\"accepted\":%" PRIu64 ",\"commits\":%" PRIu64 ","
+ "\"gets\":%" PRIu64 ",\"conflicts\":%" PRIu64 ",\"budget_rejections\":%" PRIu64 ","
+ "\"expired\":%" PRIu64 ",\"releases\":%" PRIu64 ",\"ingress_prefix_copy_bytes\":%" PRIu64 ","
+ "\"borrowed_output_bytes\":%" PRIu64 ",\"server_structure_bytes\":%zu}\n",
+ server.active, server.retained, server.peak_retained, server.budget, server.peak_active,
+ server.accepted, server.commits, server.gets, server.conflicts, server.budget_rejections,
+ server.expired, server.releases, server.prefix_copy_bytes, server.borrowed_output_bytes, sizeof(server));
+ return 0;
+usage:
+ fputs("pure-connections --program FILE --store DIRECTORY [--port 8767] [--budget BYTES] [--timeout-ms 10000] [--send-buffer BYTES]\n"
+ "pure-connections --check-program FILE\n", stderr);
+ return 2;
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/store.c b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/store.c
new file mode 100644
index 0000000..1c13a80
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/store.c
@@ -0,0 +1,228 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Immutable extent envelope: marker, little-endian u64 revision and payload
+ * length, then unchanged caller bytes. Single-threaded control API; cooperating
+ * processes serialize publication using .writer.lock. */
+enum { HEADER_BYTES = 24 };
+static const unsigned char magic[8] = {'P','U','R','E','B','0','0','1'};
+static uint64_t temporary_sequence;
+
+static bool fault(PureStoreStage stage) {
+#ifdef PURE_STORE_TEST
+ if (pure_store_test_fault(stage)) { errno = EIO; return true; }
+#else
+ (void)stage;
+#endif
+ return false;
+}
+
+static bool file_name(const char *key, char name[72]) {
+ if (!key) return false;
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ snprintf(name, 72, "obj-%s", key);
+ return true;
+}
+
+static uint64_t decode64(const unsigned char *bytes) {
+ uint64_t value = 0;
+ for (unsigned i = 0; i < 8; ++i) value |= (uint64_t)bytes[i] << (8 * i);
+ return value;
+}
+
+static void encode64(unsigned char *bytes, uint64_t value) {
+ for (unsigned i = 0; i < 8; ++i) bytes[i] = (unsigned char)(value >> (8 * i));
+}
+
+static bool sync_fd(int fd) {
+ int rc;
+ do { rc = fsync(fd); } while (rc && errno == EINTR);
+ return rc == 0;
+}
+
+static bool write_bytes(int fd, const unsigned char *bytes, size_t length) {
+ while (length) {
+ ssize_t n = write(fd, bytes, length);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ bytes += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static bool read_header(int fd, int64_t *revision, size_t *length) {
+ struct stat info;
+ if (fstat(fd, &info) || !S_ISREG(info.st_mode)) return false;
+ unsigned char header[HEADER_BYTES];
+ size_t used = 0;
+ while (used < sizeof(header)) {
+ ssize_t n = pread(fd, header + used, sizeof(header) - used, (off_t)used);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ used += (size_t)n;
+ }
+ uint64_t version = decode64(header + 8), size = decode64(header + 16);
+ if (memcmp(header, magic, sizeof(magic)) || !version || version > INT64_MAX ||
+ size > PURE_OBJECT_LIMIT || info.st_size != (off_t)(HEADER_BYTES + size)) return false;
+ *revision = (int64_t)version;
+ *length = (size_t)size;
+ return true;
+}
+
+PureResult pure_store_init(const char *path) {
+ if (!path || !*path) return PURE_STORE_ERROR;
+ bool created = mkdir(path, 0700) == 0;
+ if (!created && errno != EEXIST) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR; /* Never reinterpret an old DB file. */
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600);
+ struct stat info;
+ bool ok = lock >= 0 && fstat(lock, &info) == 0 && S_ISREG(info.st_mode) && sync_fd(lock);
+ if (lock >= 0) close(lock);
+ if (ok) ok = sync_fd(directory);
+ close(directory);
+ if (!ok) return PURE_STORE_ERROR;
+ if (created) {
+ char *parent = strdup(path);
+ if (!parent) return PURE_STORE_ERROR;
+ size_t length = strlen(parent);
+ while (length > 1 && parent[length - 1] == '/') parent[--length] = 0;
+ char *slash = strrchr(parent, '/');
+ if (!slash) strcpy(parent, ".");
+ else if (slash == parent) parent[1] = 0;
+ else *slash = 0;
+ int fd = open(parent, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ free(parent);
+ ok = fd >= 0 && sync_fd(fd);
+ if (fd >= 0) close(fd);
+ }
+ return ok ? PURE_OK : PURE_STORE_ERROR;
+}
+
+void pure_store_release(PureStoredView *view) {
+ if (view->mapped_size) munmap(view->mapping, view->mapped_size);
+ *view = (PureStoredView){0};
+}
+
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out) {
+ *out = (PureStoredView){0};
+ char name[72];
+ if (!file_name(key, name)) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ int cause = errno;
+ close(directory);
+ if (fd < 0) return cause == ENOENT ? PURE_NOT_FOUND : PURE_STORE_ERROR;
+ int64_t revision;
+ size_t size;
+ PureResult result = PURE_STORE_ERROR;
+ if (!read_header(fd, &revision, &size)) goto finish;
+ if (size < minimum) { result = PURE_LIMIT; goto finish; }
+ if (offset > size) { result = PURE_LIMIT; goto finish; }
+ if (whole) length = size - offset;
+ if (offset > size || length > size - offset) { result = PURE_LIMIT; goto finish; }
+ if (length > available) { result = PURE_BUDGET; goto finish; }
+ if (length) {
+ long page = sysconf(_SC_PAGESIZE);
+ if (page <= 0) goto finish;
+ size_t start = HEADER_BYTES + offset;
+ size_t aligned = start - start % (size_t)page;
+ size_t prefix = start - aligned;
+ size_t mapped_size = prefix + length;
+ void *mapping = mmap(NULL, mapped_size, PROT_READ, MAP_PRIVATE, fd, (off_t)aligned);
+ if (mapping == MAP_FAILED) goto finish;
+ out->mapping = mapping;
+ out->mapped_size = mapped_size;
+ out->body = (PureSpan){(const unsigned char *)mapping + prefix, length};
+ }
+ out->revision = revision;
+ out->object_size = size;
+ result = PURE_OK;
+finish:
+ close(fd); /* The mapping retains this immutable file version after rename. */
+ return result;
+}
+
+PureResult pure_store_get(const char *path, const char *key, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, 0, 0, true, 0, available, out);
+}
+
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, offset, length, false, 0, available, out);
+}
+
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ *revision = 0;
+ char name[72], temporary[96] = "";
+ if (!file_name(key, name) || (body.size && !body.data)) return PURE_STORE_ERROR;
+ if (body.size > PURE_OBJECT_LIMIT || expected < 0) return PURE_LIMIT;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_NOFOLLOW | O_CLOEXEC);
+ int fd = -1;
+ PureResult result = PURE_STORE_ERROR;
+ struct stat info;
+ if (lock < 0 || fstat(lock, &info) || !S_ISREG(info.st_mode)) goto finish;
+ struct flock hold = {.l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0};
+ if (fcntl(lock, F_SETLK, &hold)) {
+ if (errno == EACCES || errno == EAGAIN) result = PURE_BUSY;
+ goto finish;
+ }
+ fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (fd >= 0) {
+ size_t size;
+ if (!read_header(fd, revision, &size)) goto finish;
+ close(fd);
+ fd = -1;
+ } else if (errno != ENOENT) goto finish;
+ if (*revision != expected) { result = PURE_CONFLICT; goto finish; }
+ if (*revision == INT64_MAX) { result = PURE_LIMIT; goto finish; }
+ for (unsigned attempt = 0; attempt < 64; ++attempt) {
+ if (temporary_sequence == UINT64_MAX) goto finish;
+ snprintf(temporary, sizeof(temporary), ".pending-%ld-%" PRIu64, (long)getpid(), ++temporary_sequence);
+ fd = openat(directory, temporary, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
+ if (fd >= 0) break;
+ temporary[0] = 0; /* Never remove an existing file on a name collision. */
+ if (errno != EEXIST) goto finish;
+ }
+ if (fd < 0) goto finish;
+ unsigned char header[HEADER_BYTES];
+ memcpy(header, magic, sizeof(magic));
+ encode64(header + 8, (uint64_t)*revision + 1);
+ encode64(header + 16, body.size);
+ if (!write_bytes(fd, header, sizeof(header)) || fault(PURE_AFTER_HEADER) ||
+ !write_bytes(fd, body.data, body.size) || fault(PURE_BEFORE_FILE_SYNC) || !sync_fd(fd)) goto finish;
+ int close_result = close(fd);
+ fd = -1;
+ if (close_result || fault(PURE_BEFORE_RENAME) || renameat(directory, temporary, directory, name)) goto finish;
+ temporary[0] = 0; /* Published: a later sync failure does not roll it back. */
+ ++*revision;
+ result = fault(PURE_BEFORE_DIR_SYNC) || !sync_fd(directory) ? PURE_UNCERTAIN : PURE_OK;
+finish:
+ if (fd >= 0) close(fd);
+ if (*temporary) unlinkat(directory, temporary, 0);
+ if (lock >= 0) close(lock);
+ close(directory);
+ return result;
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/store.h b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/store.h
new file mode 100644
index 0000000..c0b2564
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/store.h
@@ -0,0 +1,40 @@
+#ifndef PURE_STORE_H
+#define PURE_STORE_H
+#include "flow.h"
+#include <stdint.h>
+
+#define PURE_OBJECT_LIMIT ((2u * 6u + 32u) * 32768u + 8192u)
+typedef enum {
+ PURE_OK, PURE_NOT_FOUND, PURE_CONFLICT, PURE_BUSY, PURE_BUDGET,
+ PURE_LIMIT, PURE_STORE_ERROR, PURE_UNCERTAIN
+} PureResult;
+typedef struct {
+ void *mapping;
+ size_t mapped_size, object_size;
+ PureSpan body;
+ int64_t revision;
+} PureStoredView;
+
+PureResult pure_store_init(const char *path);
+PureResult pure_store_get(const char *path, const char *key, size_t available,
+ PureStoredView *out);
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out);
+/* Inspect once: guards and mapping refer to the same immutable file version.
+ * minimum preserves bounds checks from eliminated intermediate views.
+ * whole selects the suffix starting at offset; otherwise length is exact. */
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out);
+void pure_store_release(PureStoredView *);
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision);
+
+/* Fault hooks exist only in the separately built unit-test binary. */
+typedef enum {
+ PURE_AFTER_HEADER, PURE_BEFORE_FILE_SYNC, PURE_BEFORE_RENAME, PURE_BEFORE_DIR_SYNC
+} PureStoreStage;
+#ifdef PURE_STORE_TEST
+int pure_store_test_fault(PureStoreStage stage);
+#endif
+#endif
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-fields.c b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-fields.c
new file mode 100644
index 0000000..63dfc3e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-fields.c
@@ -0,0 +1,153 @@
+#include "program.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static const char layout[] = "layout Envelope { marker: bytes[1]; start: u32le; count: u32le; text: bytes; }";
+static PureProgram parse(const char *source) {
+ PureProgram p;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &p, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return p;
+}
+static void invalid(const char *source) {
+ PureProgram p;
+ memset(&p, 0x5a, sizeof(p));
+ unsigned char before[sizeof(p)];
+ memcpy(before, &p, sizeof(p));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(*error && !memcmp(before, &p, sizeof(p)));
+}
+static void encode(unsigned char *at, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) at[i] = (unsigned char)(value >> (8 * i));
+}
+int main(void) {
+ char source[8000];
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let alias = input; let start = alias.start; let text = alias.text; "
+ "let selected = range(text, start, alias.count); let result = selected; "
+ "let saved = store.write(request.key, request.revision, result); reply(saved, selected); }", layout, get);
+ PureProgram p = parse(source);
+ CHECK(p.input_steps == 1 && p.input_required == 9 && p.write_step == 1 && p.reply_step == 1);
+ CHECK(p.steps[0].source.offset == 9 && p.steps[0].source.to_end);
+ CHECK(p.steps[0].offset.value == 1 && p.steps[0].offset.from_u32le);
+ CHECK(p.steps[0].length.value == 5 && p.steps[0].length.from_u32le);
+ unsigned char bytes[609];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 13);
+ PureSpan stored, returned;
+ for (size_t n = 0; n < 9; ++n) {
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, n}, &stored, &returned));
+ CHECK(!stored.size && !returned.size);
+ }
+ const uint32_t offsets[] = {0, 1, 255, 257, 599, 600, 601, UINT32_MAX};
+ const uint32_t counts[] = {0, 1, 2, 260, 600, UINT32_MAX};
+ size_t comparisons = 0;
+ for (size_t i = 0; i < sizeof(offsets) / sizeof(*offsets); ++i)
+ for (size_t j = 0; j < sizeof(counts) / sizeof(*counts); ++j) {
+ uint32_t start = offsets[i], count = counts[j];
+ encode(bytes + 1, start);
+ encode(bytes + 5, count);
+ bool expected = start <= 600 && count <= 600 - start;
+ CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned) == expected);
+ if (expected) {
+ CHECK(stored.size == count && returned.size == count && stored.data == returned.data);
+ CHECK(!count || stored.data == bytes + 9 + start);
+ } else CHECK(!stored.size && !returned.size);
+ ++comparisons;
+ }
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let first = range(input.text, input.start, input.count); let second = range(first, 1, 2); "
+ "let saved = store.write(request.key, request.revision, second); reply(saved, second); }", layout, get);
+ p = parse(source);
+ CHECK(p.input_steps == 2 && p.steps[1].source_step == 1);
+ encode(bytes + 1, 3); encode(bytes + 5, 4);
+ CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+ CHECK(stored.size == 2 && stored.data == bytes + 13);
+ encode(bytes + 5, 2);
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let unused = range(input.text, input.start, input.count); "
+ "let saved = store.write(request.key, request.revision, input.text); reply(saved); }", layout, get);
+ p = parse(source);
+ encode(bytes + 1, UINT32_MAX);
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+
+ snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); "
+ "let input = view(Envelope, o.body); reply(o, input.text); } %s", layout, put);
+ p = parse(source);
+ CHECK(p.read.to_end && p.read.offset == 9 && p.read_required == 9 && !p.input_steps);
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let selection = range(input.text, 2, 3); let saved = store.write(request.key, request.revision, selection); reply(saved); }", layout, get);
+ p = parse(source);
+ CHECK(!p.input_steps && p.write.offset == 11 && p.write.length == 3 && p.input_required == 14);
+ snprintf(source, sizeof(source), "layout Empty { body: bytes; } %s on put { let input = view(Empty, request.body); "
+ "let saved = store.write(request.key, request.revision, input.body); reply(saved, input.body); }", get);
+ p = parse(source);
+ CHECK(pure_program_input(&p, (PureSpan){0}, &stored, &returned) && !stored.size && !returned.size);
+
+ const char *bad_layout[] = {
+ "layout E {}", "layout E { x: bytes; y: u32le; }", "layout E { x: u32le; x: bytes; }",
+ "layout E { x: bytes[1449985]; }", "layout E { x: bytes[1449984]; y: u32le; }",
+ "layout E { x: bytes[184467440737095516160]; }", "layout E { x: u64le; }",
+ "layout E { x: u32le; } layout E { y: bytes; }"
+ };
+ for (size_t i = 0; i < sizeof(bad_layout) / sizeof(*bad_layout); ++i) {
+ snprintf(source, sizeof(source), "%s %s %s", bad_layout[i], get, put); invalid(source);
+ }
+ const char *bad_input[] = {
+ "let input = view(Missing, request.body);",
+ "let input = view(Envelope, request.body); let x = input.missing;",
+ "let input = view(Envelope, request.body); let x = range(input.text, input.text, 1);",
+ "let short = range(request.body, 0, 8); let input = view(Envelope, short);",
+ "let input = view(Envelope, request.body); let x = range(input.text, input.start, 20); let y = view(Envelope, x);"
+ };
+ for (size_t i = 0; i < sizeof(bad_input) / sizeof(*bad_input); ++i) {
+ snprintf(source, sizeof(source), "%s %s on put { %s let saved = store.write(request.key, request.revision, request.body); reply(saved); }", layout, get, bad_input[i]);
+ invalid(source);
+ }
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let saved = store.write(request.key, request.revision, input.start); reply(saved); }", layout, get);
+ invalid(source);
+ snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); let input = view(Envelope, o.body); "
+ "let x = range(input.text, input.start, input.count); reply(o, x); } %s", layout, put);
+ invalid(source);
+ for (size_t count = 8; count <= 9; ++count) {
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); ", layout, get);
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let v%zu = range(input.text, input.start, input.count); ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let saved = store.write(request.key, request.revision, input.text); reply(saved); }");
+ if (count == 8) CHECK(parse(source).input_steps == 8); else invalid(source);
+ }
+ for (size_t count = 4; count <= 5; ++count) {
+ source[0] = 0;
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "layout L%zu { body: bytes; } ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "%s %s", get, put);
+ if (count == 4) (void)parse(source); else invalid(source);
+ }
+ for (size_t count = 16; count <= 17; ++count) {
+ strcpy(source, "layout L { ");
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "f%zu: u32le; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "} %s %s", get, put);
+ if (count == 16) (void)parse(source); else invalid(source);
+ }
+ printf("{\"fields\":\"named-layouts-unaligned-u32le-tail-dynamic-ranges-aliases-failures-limits\","
+ "\"data_boundary_cases\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-flow.c b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-flow.c
new file mode 100644
index 0000000..5ff028d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-flow.c
@@ -0,0 +1,183 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static int failed_stage = -1;
+static bool crash_at_stage;
+int pure_store_test_fault(PureStoreStage stage) {
+ if ((int)stage != failed_stage) return 0;
+ if (crash_at_stage) _exit(77);
+ return 1;
+}
+typedef struct { unsigned char *bytes; unsigned releases; } Owner;
+static void release(void *raw) {
+ Owner *owner = raw;
+ free(owner->bytes);
+ owner->bytes = NULL;
+ ++owner->releases;
+}
+
+static void transfers(void) {
+ Owner owner = {.bytes = malloc(5)};
+ CHECK(owner.bytes);
+ memcpy(owner.bytes, "a\0bcd", 5);
+ PureTransfer transfer = {0};
+ pure_transfer_init(&transfer, (PureSpan){(const unsigned char *)"head", 4},
+ (PureSpan){owner.bytes, 5}, &owner, release);
+ CHECK(!pure_transfer_consume(&transfer, 5));
+ CHECK(transfer.active && !owner.releases);
+ CHECK(pure_transfer_consume(&transfer, 0));
+ unsigned char received[9];
+ size_t used = 0;
+ while (transfer.active) {
+ PureSpan span = pure_transfer_next(&transfer, 2);
+ CHECK(span.size && span.size <= 2);
+ memcpy(received + used, span.data, span.size);
+ used += span.size;
+ CHECK(pure_transfer_consume(&transfer, span.size));
+ CHECK((used == 9) == (owner.releases == 1));
+ }
+ CHECK(used == 9 && !memcmp(received, "heada\0bcd", 9));
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 1 && !pure_transfer_consume(&transfer, 0));
+ owner.bytes = malloc(3);
+ CHECK(owner.bytes);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){owner.bytes, 3}, &owner, release);
+ CHECK(pure_transfer_consume(&transfer, 1));
+ pure_transfer_abort(&transfer);
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 2 && !transfer.active);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){0}, &owner, release);
+ CHECK(owner.releases == 3 && !transfer.active);
+}
+
+static void storage(const char *path) {
+ CHECK(pure_store_init(path) == PURE_OK);
+ PureStoredView first, second;
+ CHECK(pure_store_get(path, "missing", 100, &first) == PURE_NOT_FOUND);
+ CHECK(!first.mapping && !first.mapped_size);
+ static const unsigned char original[] = {0, 1, 2, 255, 17};
+ static const unsigned char updated[] = {9, 8, 7};
+ int64_t revision;
+ CHECK(pure_store_put(path, "work", 0, (PureSpan){original, sizeof(original)}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ CHECK(pure_store_get(path, "work", sizeof(original) - 1, &first) == PURE_BUDGET);
+ CHECK(!first.mapping && !first.mapped_size);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 3, &first) == PURE_OK);
+ CHECK(first.object_size == sizeof(original) && first.body.size == 3 && !memcmp(first.body.data, original + 1, 3));
+ pure_store_release(&first);
+ CHECK(pure_store_get_range(path, "work", SIZE_MAX, 1, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, SIZE_MAX, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 2, &first) == PURE_BUDGET);
+ CHECK(pure_store_get_range(path, "work", sizeof(original), 0, 0, &first) == PURE_OK);
+ CHECK(!first.mapped_size && !first.body.size);
+ pure_store_release(&first);
+ CHECK(pure_store_get(path, "work", sizeof(original), &first) == PURE_OK);
+ CHECK(first.body.size == sizeof(original) && first.revision == 1);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 2);
+ CHECK(!memcmp(first.body.data, original, sizeof(original)));
+ CHECK(pure_store_get(path, "work", 100, &second) == PURE_OK);
+ CHECK(second.revision == 2 && second.body.size == sizeof(updated));
+ CHECK(!memcmp(second.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ pure_store_release(&first);
+ pure_store_release(&second);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){original, sizeof(original)}, &revision) == PURE_CONFLICT);
+ CHECK(revision == 2);
+
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 2 && !memcmp(first.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == 3);
+ failed_stage = -1;
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_CONFLICT);
+
+ /* A crashed unpublished writer leaves only a private file. A new publisher
+ * must still use the previous committed version, never an incomplete body. */
+ pid_t child = fork();
+ CHECK(child >= 0);
+ if (!child) {
+ failed_stage = PURE_AFTER_HEADER;
+ crash_at_stage = true;
+ pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision);
+ _exit(78);
+ }
+ int status;
+ CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 77);
+ CHECK(pure_store_init(path) == PURE_OK);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 4);
+
+ char file[320];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ CHECK(fd >= 0);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_put(path, "work", INT64_MAX, (PureSpan){original, sizeof(original)}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_put(path, "empty", 0, (PureSpan){0}, &revision) == PURE_OK);
+ CHECK(pure_store_get(path, "empty", 0, &first) == PURE_OK && first.body.size == 0);
+ pure_store_release(&first);
+
+ /* Range mapping crosses page boundaries without copying a whole object. */
+ long page = sysconf(_SC_PAGESIZE);
+ CHECK(page >= 128 && (size_t)page <= PURE_OBJECT_LIMIT / 3);
+ size_t size = (size_t)page * 3, offset = (size_t)page + 13, length = (size_t)page + 105;
+ unsigned char *bytes = malloc(size);
+ CHECK(bytes);
+ for (size_t i = 0; i < size; ++i) bytes[i] = (unsigned char)((i * 17u) ^ (i >> 8) ^ (i >> 16));
+ CHECK(pure_store_put(path, "range", 0, (PureSpan){bytes, size}, &revision) == PURE_OK);
+ CHECK(pure_store_get_range(path, "range", offset, length, length, &first) == PURE_OK);
+ CHECK(first.body.size == length && !memcmp(first.body.data, bytes + offset, length));
+ pure_store_release(&first);
+ free(bytes);
+ snprintf(file, sizeof(file), "%s/obj-broken", path);
+ fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0600);
+ CHECK(fd >= 0 && write(fd, "incomplete", 10) == 10 && close(fd) == 0);
+ CHECK(pure_store_get(path, "broken", 100, &first) == PURE_STORE_ERROR && !first.mapped_size);
+ CHECK(pure_store_put(path, "broken", 0, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_init(file) == PURE_STORE_ERROR);
+ struct stat info;
+ CHECK(stat(file, &info) == 0 && info.st_size == 10);
+}
+
+int main(void) {
+ transfers();
+ char directory[] = "/tmp/pure-connection-unit-XXXXXX";
+ CHECK(mkdtemp(directory));
+ char path[256];
+ snprintf(path, sizeof(path), "%s/store", directory);
+ storage(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ CHECK(rmdir(directory) == 0);
+ puts("{\"transfer\":\"partial-consumption-and-single-release\","
+ "\"storage\":\"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty\"}");
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-program.c b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-program.c
new file mode 100644
index 0000000..6a4a19d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/connections/test-program.c
@@ -0,0 +1,111 @@
+#include "program.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static PureProgram parse(const char *source) {
+ PureProgram program;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &program, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return program;
+}
+static void invalid(const char *source) {
+ PureProgram program;
+ memset(&program, 0x5a, sizeof(program));
+ unsigned char original[sizeof(program)];
+ memcpy(original, &program, sizeof(program));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &program, error, sizeof(error)));
+ CHECK(*error && !memcmp(original, &program, sizeof(program)));
+}
+int main(void) {
+ char source[4096];
+ snprintf(source, sizeof(source), "%s %s", get, put);
+ PureProgram plan = parse(source);
+ CHECK(plan.read.to_end && plan.write.to_end && !plan.reply_input);
+ CHECK(!plan.view_definitions && !plan.read_required && !plan.input_required);
+ snprintf(source, sizeof(source), "%s on put { let a = range(request.body, 2, 10); "
+ "let b = range(a, 3, 4); let alias = b; "
+ "let saved = store.write(request.key, request.revision, alias); reply(saved, b); }", get);
+ plan = parse(source);
+ CHECK(plan.write.offset == 5 && plan.write.length == 4 && !plan.write.to_end);
+ CHECK(plan.reply.offset == 5 && plan.reply.length == 4 && plan.reply_input);
+ CHECK(plan.input_required == 12 && plan.range_definitions == 2 && plan.view_definitions == 3);
+ /* Ordered reference views keep even unused bounds failures observable. */
+ unsigned char bytes[160];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 7);
+ size_t comparisons = 0;
+ for (size_t a = 0; a < 4; ++a) for (size_t b = 0; b < 6; ++b)
+ for (size_t c = 0; c <= b; ++c) for (size_t d = 0; d <= b - c; ++d) {
+ size_t unused_end = (a + b + c) % 12;
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); "
+ "let unused = range(o.body, %zu, 0); let first = range(o.body, %zu, %zu); "
+ "let second = range(first, %zu, %zu); reply(o, second); } %s",
+ unused_end, a, b, c, d, put);
+ plan = parse(source);
+ for (size_t n = 0; n < 16; ++n) {
+ bool reference_ok = unused_end <= n && a <= n && b <= n - a;
+ PureSpan selected;
+ bool prepared_ok = n >= plan.read_required &&
+ pure_region_span(plan.read, (PureSpan){bytes, n}, &selected);
+ CHECK(reference_ok == prepared_ok);
+ if (reference_ok) {
+ CHECK(selected.size == d);
+ CHECK(!d || !memcmp(selected.data, bytes + a + c, d));
+ }
+ ++comparisons;
+ }
+ }
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); reply(o); } %s", put);
+ plan = parse(source);
+ CHECK(!plan.read.to_end && !plan.read.length);
+ const char *bad_get[] = {
+ "on get { let o = store.read(request.key); let x = range(o.body, 0, 2); let y = range(x, 2, 1); reply(o, y); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 184467440737095516160, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 1449984, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let o = o.body; reply(o); }",
+ "on get { let o = store.read(request.key); let x = x; reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = store.read(request.key); reply(x); }",
+ "on get { let o = store.read(request.key); reply(o, request.body); }",
+ "on get { let o = store.read(request.key); let x = o.body; reply(x); }",
+ "on get { let o = store.read(request.key); reply(o.body); }",
+ "on get { let o = store.read(request.key); reply(o); let x = o.body; }",
+ "on get { let o = store.read(request.key); reply(o);", "on get {}"
+ };
+ for (size_t i = 0; i < sizeof(bad_get) / sizeof(*bad_get); ++i) {
+ snprintf(source, sizeof(source), "%s %s", bad_get[i], put); invalid(source);
+ }
+ const char *bad_put[] = {
+ "on put { let s = store.write(request.key, request.revision, request.body); let b = range(request.body, 0, 1); reply(s, b); }",
+ "on put { let s = store.write(request.key, request.revision, request.body); reply(s, s.body); }",
+ "on put { let s = store.read(request.key); reply(s); }"
+ };
+ for (size_t i = 0; i < sizeof(bad_put) / sizeof(*bad_put); ++i) {
+ snprintf(source, sizeof(source), "%s %s", get, bad_put[i]); invalid(source);
+ }
+ invalid(get);
+ snprintf(source, sizeof(source), "%s %s %s", get, get, put); invalid(source);
+ snprintf(source, sizeof(source), "%s %s garbage", get, put); invalid(source);
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); ");
+ for (size_t i = 0; i < 32; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let x%zu = o.body; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "reply(o); } %s", put); invalid(source);
+ char oversized[PURE_PROGRAM_LIMIT + 1];
+ memset(oversized, ' ', sizeof(oversized));
+ char error[160];
+ CHECK(!pure_program_parse(oversized, sizeof(oversized), &plan, error, sizeof(error)));
+ const char embedded[] = "on get\0{}";
+ CHECK(!pure_program_parse(embedded, sizeof(embedded) - 1, &plan, error, sizeof(error)));
+ PureSpan selected;
+ CHECK(pure_region_span((PureRegion){0}, (PureSpan){0}, &selected) && !selected.data && !selected.size);
+ printf("{\"program\":\"prepare-views-preserve-guards-types-effects-and-atomic-install\","
+ "\"boundary_semantic_comparisons\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/cli.mjs b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/cli.mjs
new file mode 100644
index 0000000..b67f4d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/cli.mjs
@@ -0,0 +1,127 @@
+#!/usr/bin/env node
+import { readFile, writeFile } from 'node:fs/promises';
+import { createInterface } from 'node:readline';
+import { createRuntime } from './web/runtime.mjs';
+import { parseProject } from './web/project.mjs';
+import { remoteTarget, pushProject, pullProject } from './remote.mjs';
+
+const help = `Pure authoring workbench · 같은 정의와 Zig 실행기
+ load PATH .pure 파일을 적용 (같은 이름의 상태 보존)
+ down NAME 정의한 입력 누르기
+ up NAME 정의한 입력 놓기
+ point NAME PHASE X Y 좌표 입력 (down / move / up / cancel)
+ point-target NAME VIEW PHASE X Y 그룹의 대상에 좌표 입력
+ change NAME VALUE 숫자 입력 전달
+ frame [1..600] 시간 진행, 1프레임 = 1/60초
+ show 상태와 도형 출력
+ limits C H W 표시 캐시(0..32)·변경 기록(0..8)·작업량(0..4294967295) 설정
+ forget [PART] 표시 기록 삭제: all, values, history (상태는 유지)
+ costs 마지막 표시 계산의 작업량·명령 수·캐시 적중 출력
+ reset 현재 정의의 초기 상태로
+ save PATH 적용한 정의를 저장
+ save-project PATH 적용 코드와 현재 배치를 JSON으로 저장
+ restore PATH 저장한 배치를 복원 (초안이 있으면 파일에 보존)
+ connect URL KEY 로컬 네이티브 저장 서버의 작업물에 연결
+ push [REVISION] 현재 배치를 저장 (첫 생성은 push 0, 충돌 시 기존 값 유지)
+ pull 원격 배치를 검증·복원하고 revision 기억
+ help / quit
+브라우저와 별도 인스턴스입니다. 임의 JavaScript는 실행하지 않습니다.`;
+
+async function main() {
+ const args = process.argv.slice(2);
+ if (args.includes('--help')) { console.log(help); return; }
+ if (args.length > 1) throw new Error('사용법: node cli.mjs [project.pure]');
+ const runtime = await createRuntime(await readFile(new URL('./web/core.wasm', import.meta.url)));
+ let savedDraft = null;
+ let remote = null, remoteRevision = null;
+ async function loadFile(path, restoreOnly = false) {
+ const content = await readFile(path, 'utf8');
+ if (restoreOnly || path.toLowerCase().endsWith('.json')) {
+ const project = parseProject(content);
+ if (project.version === 2) {
+ savedDraft = runtime.restoreDocument(project).draft;
+ return;
+ }
+ if (restoreOnly) throw new Error('현재 배치가 포함된 version 2 파일이 필요합니다.');
+ runtime.apply(project.source);
+ } else runtime.apply(content);
+ savedDraft = null;
+ }
+ if (args[0]) await loadFile(args[0]); else runtime.apply('');
+ const terminal = createInterface({ input: process.stdin, output: process.stdout, terminal: Boolean(process.stdin.isTTY) });
+ if (process.stdin.isTTY) console.log(help);
+ terminal.setPrompt('pure> ');
+ if (process.stdin.isTTY) terminal.prompt();
+ for await (const line of terminal) {
+ try {
+ const match = /^(\S+)(?:\s+(.+))?$/.exec(line.trim());
+ const name = match?.[1] || 'show';
+ const arg = match?.[2];
+ if (name === 'quit') { terminal.close(); break; }
+ if (name === 'help') console.log(help);
+ else if (name === 'costs' && !arg) console.log(JSON.stringify({ evaluation: runtime.evaluationStats() }));
+ else {
+ if (name === 'load' && arg) await loadFile(arg);
+ else if (name === 'restore' && arg) await loadFile(arg, true);
+ else if (name === 'connect' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('connect URL KEY 형식을 사용하세요.');
+ remote = remoteTarget(parts[0], parts[1]);
+ remoteRevision = null;
+ console.log(JSON.stringify({ remote: remote.href }));
+ } else if (name === 'push') {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const expected = arg ?? remoteRevision;
+ if (expected === null) throw new Error('먼저 pull로 버전을 읽거나 push 0으로 새 작업물을 만드세요.');
+ remoteRevision = await pushProject(remote, expected, runtime.exportDocument(savedDraft ?? undefined));
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, stored: true }));
+ } else if (name === 'pull' && !arg) {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const loaded = await pullProject(remote);
+ savedDraft = runtime.restoreDocument(loaded.project).draft;
+ remoteRevision = loaded.revision;
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, restored: true }));
+ }
+ else if (name === 'save-project' && arg) await writeFile(arg, JSON.stringify(runtime.exportDocument(savedDraft ?? undefined), null, 2) + '\n', {flag:'wx'});
+ else if (name === 'save' && arg) await writeFile(arg, runtime.exportProject().source, { flag: 'wx' });
+ else if (name === 'down' && arg) runtime.down(arg, 'terminal');
+ else if (name === 'up' && arg) runtime.up(arg, 'terminal');
+ else if (name === 'point' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 4) throw new Error('point NAME PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[1], Number(parts[2]), Number(parts[3]), 'terminal');
+ } else if (name === 'point-target' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 5) throw new Error('point-target NAME VIEW PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[2], Number(parts[3]), Number(parts[4]), 'terminal', parts[1]);
+ } else if (name === 'change' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('change NAME VALUE 형식을 사용하세요.');
+ runtime.change(parts[0], Number(parts[1]), 'terminal');
+ } else if (name === 'frame') {
+ if (arg !== undefined && !/^\d+$/.test(arg)) throw new Error('frame 1..600 정수를 입력하세요.');
+ const count = arg === undefined ? 1 : Number(arg);
+ if (count < 1 || count > 600) throw new Error('frame 1..600 정수를 입력하세요.');
+ runtime.frame(count);
+ } else if (name === 'reset' && !arg) runtime.reset();
+ else if (name === 'limits' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 3 || parts.some(part => !/^\d+$/.test(part)))
+ throw new Error('limits C H W 정수 세 개를 입력하세요.');
+ const [cacheEntries, historyEntries, workLimit] = parts.map(Number);
+ runtime.configureEvaluation({ cacheEntries, historyEntries, workLimit });
+ } else if (name === 'forget') runtime.forgetEvaluation(arg || 'all');
+ else if (name !== 'show' || arg) throw new Error('명령 형식을 확인하세요. help로 안내를 볼 수 있습니다.');
+ const result = runtime.snapshot();
+ console.log(JSON.stringify(result));
+ if (result.lastError && !process.stdin.isTTY) process.exitCode = 1;
+ }
+ } catch (error) {
+ console.error(`${error.line ? `${error.line}:${error.column || 1} ` : ''}${error.message}`);
+ if (!process.stdin.isTTY) process.exitCode = 1;
+ }
+ if (process.stdin.isTTY) terminal.prompt();
+ }
+}
+
+main().catch((error) => { console.error(error.message); process.exitCode = 1; });
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/examples/direct.pure b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/examples/direct.pure
new file mode 100644
index 0000000..b29721c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/examples/direct.pure
@@ -0,0 +1,47 @@
+# 도형을 잡은 위치를 유지해 이동합니다. 취소하면 잡기 전 위치로 돌아갑니다.
+state x = 80
+state y = 160
+state grab_x = 0
+state grab_y = 0
+state start_x = 80
+state start_y = 160
+state dragging = 0
+
+input drag = pointer(tile)
+input left = ArrowLeft
+input right = ArrowRight
+
+box left_area(20, 100, 280, 220, "#233a31")
+box right_area(340, 100, 280, 220, "#343b25")
+box tile(x, y, 56, 44, "#c9f08b")
+text horizontal(30, 45, x, "x: ")
+text vertical(180, 45, y, "y: ")
+text region(350, 70, x >= 320, "오른쪽 영역: ")
+text active(30, 75, dragging, "잡고 있음: ")
+
+on drag.down {
+ start_x = x
+ start_y = y
+ grab_x = event_x - x
+ grab_y = event_y - y
+ dragging = 1
+}
+on drag.move {
+ x = clamp(event_x - grab_x, 20, 564)
+ y = clamp(event_y - grab_y, 100, 276)
+}
+on drag.up {
+ # 놓기는 마지막으로 표시한 위치를 확정합니다.
+ dragging = 0
+}
+on drag.cancel {
+ x = start_x
+ y = start_y
+ dragging = 0
+}
+on left.down {
+ if dragging == 0 { x = max(20, x - 10) }
+}
+on right.down {
+ if dragging == 0 { x = min(564, x + 10) }
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/remote.mjs b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/remote.mjs
new file mode 100644
index 0000000..6ee6a59
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/remote.mjs
@@ -0,0 +1,89 @@
+import http from 'node:http';
+import { MAX_PROJECT_BYTES, parseProject } from './web/project.mjs';
+
+const maxRevision = 9223372036854775807n;
+function revisionText(value, allowZero = false) {
+ if (typeof value !== 'string' || !/^(0|[1-9]\d*)$/.test(value) ||
+ value.length > 19 || BigInt(value) > maxRevision || (!allowZero && value === '0'))
+ throw new Error('revision은 범위 안의 정수 문자열이어야 합니다.');
+ return value;
+}
+
+export function remoteTarget(base, key) {
+ const url = new URL(base);
+ if (url.protocol !== 'http:' || !['127.0.0.1', 'localhost'].includes(url.hostname) ||
+ url.username || url.password || url.pathname !== '/' || url.search || url.hash)
+ throw new Error('현재 연결 호스트는 로컬 http://127.0.0.1:PORT 형식을 사용합니다.');
+ if (!/^[A-Za-z0-9_-]{1,64}$/.test(key)) throw new Error('작업물 이름은 영문·숫자·_·- 1~64자입니다.');
+ url.hostname = '127.0.0.1';
+ url.pathname = `/objects/${key}`;
+ return url;
+}
+
+function request(url, method, body, headers = {}) {
+ return new Promise((resolve, reject) => {
+ let done = false;
+ const finish = (error, value) => {
+ if (done) return;
+ done = true;
+ clearTimeout(deadline);
+ if (error) reject(error); else resolve(value);
+ };
+ const req = http.request(url, { method, agent: false, headers: { ...headers,
+ 'Content-Length': body?.byteLength ?? 0, Connection: 'close' } }, (res) => {
+ const chunks = [];
+ let size = 0;
+ res.on('data', (chunk) => {
+ size += chunk.length;
+ if (size > MAX_PROJECT_BYTES) {
+ const error = new Error('서버 작업물이 허용 크기를 넘었습니다.');
+ finish(error);
+ res.destroy(error);
+ req.destroy(error);
+ } else chunks.push(chunk);
+ });
+ res.on('error', (error) => finish(error));
+ res.on('aborted', () => finish(new Error('응답이 완료되기 전에 연결이 끊겼습니다.')));
+ res.on('end', () => {
+ if (res.statusCode !== 200) {
+ const error = new Error(`원격 작업 실패: ${res.statusCode} ${res.headers['x-pure-error'] ?? ''}`.trim());
+ error.status = res.statusCode;
+ error.etag = res.headers.etag;
+ finish(error);
+ return;
+ }
+ try {
+ const match = /^"([1-9]\d*)"$/.exec(res.headers.etag ?? '');
+ if (!match) throw new Error('서버의 revision 응답이 올바르지 않습니다.');
+ const revision = revisionText(match[1]);
+ finish(null, { revision, bytes: Buffer.concat(chunks, size) });
+ } catch (error) { finish(error); }
+ });
+ });
+ const deadline = setTimeout(() => {
+ const error = new Error('원격 작업 시간 초과: 저장 완료 여부는 다시 확인해야 합니다.');
+ finish(error);
+ req.destroy(error);
+ }, 12000);
+ req.on('error', (error) => finish(error));
+ req.end(body);
+ });
+}
+
+export async function pushProject(target, expected, project) {
+ revisionText(expected, true);
+ const text = JSON.stringify(project);
+ parseProject(text);
+ const body = Buffer.from(text, 'utf8');
+ const headers = expected === '0' ? { 'If-None-Match': '*' } : { 'If-Match': `"${expected}"` };
+ const result = await request(target, 'PUT', body, headers);
+ return result.revision;
+}
+
+export async function pullProject(target) {
+ const result = await request(target, 'GET');
+ const text = new TextDecoder('utf-8', { fatal: true }).decode(result.bytes);
+ const project = parseProject(text);
+ if (project.version !== 2) throw new Error('현재 배치를 포함한 version 2 작업물이 필요합니다.');
+ return { project, revision: result.revision };
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/compiler.mjs b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/compiler.mjs
new file mode 100644
index 0000000..6aec335
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/compiler.mjs
@@ -0,0 +1,496 @@
+// Pure's experimental scalar interaction language. No host code is evaluated.
+const LIMITS = Object.freeze({ sourceBytes: 32768, states: 32, inputs: 8,
+ views: 24, handlers: 64, instructions: 512, depth: 64, stack: 64 });
+const RESERVED = new Set(['frame', 'dt', 'event_x', 'event_y', 'event_value', 'min', 'max', 'clamp']);
+const BINARY = new Map([
+ ['||', [1, 15]], ['&&', [2, 14]], ['==', [3, 12]], ['!=', [3, 13]],
+ ['<', [4, 8]], ['<=', [4, 9]], ['>', [4, 10]], ['>=', [4, 11]],
+ ['+', [5, 3]], ['-', [5, 4]], ['*', [6, 5]], ['/', [6, 6]],
+]);
+const FUNCTIONS = { min: [2, 17], max: [2, 18], clamp: [3, 19] };
+const VIEW_FIELDS = { box: ['x', 'y', 'width', 'height'],
+ circle: ['x', 'y', 'radius'], text: ['x', 'y', 'value'] };
+
+function fail(token, message) {
+ const error = new Error(`${message} (${token.line}:${token.column})`);
+ error.line = token.line;
+ error.column = token.column;
+ throw error;
+}
+
+function lex(source) {
+ const tokens = [];
+ let offset = 0, line = 1, column = 1;
+ const advance = () => {
+ const char = source[offset++];
+ if (char === '\n') { line++; column = 1; } else column++;
+ return char;
+ };
+ while (offset < source.length) {
+ const char = source[offset];
+ if (char === ' ' || char === '\t' || char === '\r') { advance(); continue; }
+ if (char === '#') { while (offset < source.length && source[offset] !== '\n') advance(); continue; }
+ const token = { line, column };
+ if (char === '\n') { advance(); tokens.push({ ...token, kind: 'nl' }); continue; }
+ if (char === '"') {
+ advance();
+ let value = '', closed = false;
+ while (offset < source.length) {
+ const next = advance();
+ if (next === '"') { closed = true; break; }
+ if (next === '\n' || next === '\r') fail(token, 'Strings must fit on one line');
+ if (next === '\\') {
+ const escaped = advance();
+ const escapes = { n: '\n', r: '\r', t: '\t', '"': '"', '\\': '\\' };
+ if (!Object.hasOwn(escapes, escaped)) fail(token, 'Unsupported string escape');
+ value += escapes[escaped];
+ } else value += next;
+ }
+ if (!closed) fail(token, 'Unterminated string');
+ tokens.push({ ...token, kind: 'string', value }); continue;
+ }
+ const remaining = source.slice(offset);
+ const number = remaining.match(/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/);
+ if (number) {
+ const value = Number(number[0]);
+ if (!Number.isFinite(value)) fail(token, 'Number must be finite');
+ for (let i = 0; i < number[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'number', value }); continue;
+ }
+ const name = remaining.match(/^[A-Za-z_][A-Za-z_0-9]*/);
+ if (name) {
+ for (let i = 0; i < name[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'name', value: name[0] }); continue;
+ }
+ const pair = source.slice(offset, offset + 2);
+ if (['<=', '>=', '==', '!=', '&&', '||'].includes(pair)) {
+ advance(); advance(); tokens.push({ ...token, kind: pair }); continue;
+ }
+ if ('=+-*/!<>(){},.;:'.includes(char)) {
+ advance(); tokens.push({ ...token, kind: char }); continue;
+ }
+ fail(token, `Unexpected character ${JSON.stringify(char)}`);
+ }
+ tokens.push({ kind: 'eof', line, column });
+ return tokens;
+}
+
+class Parser {
+ constructor(tokens) { this.tokens = tokens; this.position = 0; this.depth = 0; }
+ peek() { return this.tokens[this.position]; }
+ take() { return this.tokens[this.position++]; }
+ is(kind, value) { return this.peek().kind === kind && (value === undefined || this.peek().value === value); }
+ expect(kind, description = kind) {
+ if (!this.is(kind)) fail(this.peek(), `Expected ${description}`);
+ return this.take();
+ }
+ newlines() { while (this.is('nl')) this.take(); }
+ separators() { while (this.is('nl') || this.is(';')) this.take(); }
+ end() {
+ if (!['nl', ';', '}', 'eof'].includes(this.peek().kind)) fail(this.peek(), 'Expected newline or semicolon');
+ this.separators();
+ }
+ reference(token) {
+ if (!this.is('.')) return token.value;
+ this.take();
+ return `${token.value}.${this.expect('name', 'field name').value}`;
+ }
+ initial() {
+ let sign = 1;
+ if (this.is('-') || this.is('+')) sign = this.take().kind === '-' ? -1 : 1;
+ return sign * this.expect('number', 'numeric state initializer').value;
+ }
+ node(token, properties, children = []) {
+ const depth = 1 + Math.max(0, ...children.map(child => child.depth));
+ if (depth > LIMITS.depth) fail(token, 'Expression nesting exceeds 64');
+ return { token, depth, ...properties };
+ }
+ expression(minimum = 0, multiline = false) {
+ if (++this.depth > LIMITS.depth) fail(this.peek(), 'Expression nesting exceeds 64');
+ if (multiline) this.newlines();
+ const token = this.take();
+ let left;
+ if (token.kind === 'number') left = this.node(token, { kind: 'constant', value: token.value });
+ else if (token.kind === '-' || token.kind === '!') {
+ const child = this.expression(7, multiline);
+ left = this.node(token, { kind: 'unary', op: token.kind === '-' ? 7 : 16, child }, [child]);
+ } else if (token.kind === '(') {
+ left = this.expression(0, true); this.newlines(); this.expect(')');
+ } else if (token.kind === 'name') {
+ if (Object.hasOwn(FUNCTIONS, token.value) && this.is('(')) {
+ this.take();
+ const args = [];
+ this.newlines();
+ if (!this.is(')')) {
+ for (;;) {
+ args.push(this.expression(0, true)); this.newlines();
+ if (!this.is(',')) break;
+ this.take();
+ }
+ }
+ this.expect(')');
+ if (args.length !== FUNCTIONS[token.value][0]) fail(token, `${token.value} expects ${FUNCTIONS[token.value][0]} arguments`);
+ left = this.node(token, { kind: 'call', op: FUNCTIONS[token.value][1], args }, args);
+ } else left = this.node(token, { kind: 'reference', name: this.reference(token) });
+ } else fail(token, 'Expected a number, state, or expression');
+ for (;;) {
+ if (multiline) this.newlines();
+ const entry = BINARY.get(this.peek().kind);
+ if (!entry || entry[0] < minimum) break;
+ const operator = this.take();
+ const right = this.expression(entry[0] + 1, multiline);
+ left = this.node(operator, { kind: 'binary', op: entry[1], left, right }, [left, right]);
+ }
+ this.depth--;
+ return left;
+ }
+ block(depth = 0) {
+ if (depth >= LIMITS.depth) fail(this.peek(), 'Handler nesting exceeds 64');
+ this.newlines(); this.expect('{'); this.separators();
+ const statements = [];
+ while (!this.is('}')) {
+ const token = this.expect('name', 'assignment, if, or closing brace');
+ if (token.value === 'if' && !this.is('=')) {
+ const condition = this.expression();
+ const body = this.block(depth + 1);
+ statements.push({ kind: 'if', token, condition, body });
+ } else {
+ const name = this.reference(token);
+ this.expect('=');
+ statements.push({ kind: 'assign', token, name, expression: this.expression() });
+ }
+ this.end();
+ }
+ this.take();
+ return statements;
+ }
+ parse() {
+ const declarations = [];
+ this.separators();
+ while (!this.is('eof')) {
+ const token = this.expect('name', 'declaration');
+ const kind = token.value;
+ if (kind === 'state') {
+ const name = this.expect('name', 'state name'); this.expect('=');
+ declarations.push({ kind, token, name, initial: this.initial() });
+ } else if (kind === 'record') {
+ const name = this.expect('name', 'record type'); this.newlines(); this.expect('{'); this.separators();
+ const fields = [];
+ while (!this.is('}')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,fields});
+ } else if (kind === 'item') {
+ const name = this.expect('name', 'item name'); this.expect('=');
+ const type = this.expect('name', 'record type'); this.expect('('); this.newlines();
+ const fields = [];
+ while (!this.is(')')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.newlines();
+ if (!this.is(',')) break;
+ this.take(); this.newlines();
+ }
+ this.expect(')'); declarations.push({kind,token,name,type,fields});
+ } else if (kind === 'rule') {
+ const name = this.expect('name', 'rule name'); this.expect('(');
+ const parameter = this.expect('name', 'record parameter'); this.expect(':');
+ const type = this.expect('name', 'record type'); this.expect(')');
+ declarations.push({kind,token,name,parameter,type,body:this.block()});
+ } else if (kind === 'input') {
+ const name = this.expect('name', 'input name'); this.expect('=');
+ const key = this.expect('name', 'keyboard code or pointer(view)');
+ if (key.value === 'value') {
+ declarations.push({kind,token,name,valueInput:true}); this.end(); continue;
+ }
+ if (key.value === 'pointer') {
+ if (this.is('{')) {
+ this.take(); this.separators(); const routes = [];
+ while (!this.is('}')) {
+ const target = this.expect('name', 'view ID'); this.expect(':');
+ const item = this.expect('name', 'item name'); routes.push({target,item}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,routes}); this.end(); continue;
+ }
+ this.expect('(');
+ const target = this.expect('name', 'view ID'); this.expect(')');
+ declarations.push({ kind, token, name, target });
+ this.end(); continue;
+ }
+ if (!/^(?:Space|Enter|Arrow(?:Left|Right|Up|Down)|Key[A-Z]|Digit[0-9])$/.test(key.value)) fail(key, 'Unsupported keyboard code');
+ declarations.push({ kind, token, name, key });
+ } else if (Object.hasOwn(VIEW_FIELDS, kind)) {
+ const name = this.expect('name', 'view ID'); this.expect('(');
+ const expressions = [];
+ for (let i = 0; i < VIEW_FIELDS[kind].length; i++) {
+ if (i) { this.newlines(); this.expect(','); }
+ expressions.push(this.expression(0, true));
+ }
+ this.newlines();
+ let color, prefix = '';
+ if (kind !== 'text') {
+ this.expect(','); this.newlines();
+ const value = this.expect('string', 'literal hex color');
+ if (!/^#[0-9a-fA-F]{6}$/.test(value.value)) fail(value, 'Color must use six hexadecimal digits, such as "#356548"');
+ color = value.value;
+ } else if (this.is(',')) { this.take(); this.newlines(); prefix = this.expect('string', 'literal text prefix').value; }
+ this.newlines(); this.expect(')');
+ declarations.push({ kind: 'view', type: kind, token, name, expressions, color, prefix });
+ } else if (kind === 'on') {
+ const event = this.expect('name', 'input name or frame');
+ let edge;
+ if (event.value !== 'frame') {
+ this.expect('.'); edge = this.expect('name', 'down, up, move or cancel');
+ if (!['down', 'up', 'move', 'cancel', 'change'].includes(edge.value)) fail(edge, 'Expected down or up, move, cancel or change');
+ }
+ if (this.is('name', 'use')) {
+ this.take(); const rule = this.expect('name', 'rule name'); this.expect('(');
+ const item = this.expect('name', 'item name or input.target');
+ const argument = this.reference(item); this.expect(')');
+ declarations.push({kind:'handler',token,event,edge,rule,item,argument});
+ } else declarations.push({ kind: 'handler', token, event, edge, body: this.block() });
+ } else fail(token, `Unknown declaration ${kind}`);
+ this.end();
+ }
+ return declarations;
+ }
+}
+
+export function compile(source) {
+ if (typeof source !== 'string') fail({ line: 1, column: 1 }, 'Source must be a string');
+ const sourceBytes = new TextEncoder().encode(source).length;
+ if (sourceBytes > LIMITS.sourceBytes) fail({ line: 1, column: 1 }, 'Source exceeds 32768 UTF-8 bytes');
+ const declarations = new Parser(lex(source)).parse();
+ const program = { states: [], inputs: [], instructions: [], handlers: [], views: [], pointerTargets: [], metrics: {} };
+ const states = new Map(), inputs = new Map(), views = new Set(), keys = new Set(), targets = new Set();
+ const records = new Map(), items = new Map(), rules = new Map();
+ const scalarNames = new Set(declarations.filter(d => d.kind === 'state').map(d => d.name.value));
+ for (const declaration of declarations) {
+ if (!['record','rule'].includes(declaration.kind)) continue;
+ const {name,fields,kind} = declaration, symbols = kind === 'record' ? records : rules;
+ if (RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (kind === 'record') {
+ if (!fields.length || fields.length > 8) fail(name, 'A record needs 1..8 fields');
+ const used = new Set();
+ for (const field of fields) {
+ if (used.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ if (RESERVED.has(field.name.value)) fail(field.name, `Reserved name ${field.name.value}`);
+ used.add(field.name.value);
+ }
+ }
+ symbols.set(name.value, declaration);
+ }
+ let handlerCount = 0;
+ for (const declaration of declarations) {
+ const { kind, name, token } = declaration;
+ if (name && RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (kind === 'record' || kind === 'rule') continue;
+ if (kind === 'item') {
+ if (items.has(name.value) || scalarNames.has(name.value)) fail(name, `Duplicate state/item ${name.value}`);
+ const record = records.get(declaration.type.value);
+ if (!record) fail(declaration.type, `Unknown record ${declaration.type.value}`);
+ const overrides = new Map();
+ for (const field of declaration.fields) {
+ if (!record.fields.some(f => f.name.value === field.name.value)) fail(field.name, `Unknown field ${field.name.value}`);
+ if (overrides.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ overrides.set(field.name.value, field.initial);
+ }
+ const base = states.size;
+ for (const field of record.fields) {
+ if (states.size >= LIMITS.states) fail(name, 'At most 32 states are allowed, including item fields');
+ const qualified = `${name.value}.${field.name.value}`, index = states.size;
+ states.set(qualified,index);
+ program.states.push({name:qualified,initial:overrides.has(field.name.value) ? overrides.get(field.name.value) : field.initial,line:token.line});
+ }
+ items.set(name.value,{type:declaration.type.value,base,count:record.fields.length});
+ } else if (kind === 'state' || kind === 'input') {
+ const symbols = kind === 'state' ? states : inputs;
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (symbols.size >= LIMITS[`${kind}s`]) fail(name, `At most ${LIMITS[`${kind}s`]} ${kind}s are allowed`);
+ symbols.set(name.value, symbols.size);
+ if (kind === 'state') program.states.push({ name: name.value, initial: declaration.initial, line: token.line });
+ else if (declaration.valueInput) {
+ program.inputs.push({name:name.value,kind:'value',line:token.line});
+ } else if (declaration.routes) {
+ if (!declaration.routes.length) fail(name, 'A pointer group needs at least one target');
+ program.inputs.push({name:name.value, routes:[], line:token.line});
+ } else if (declaration.target) {
+ const target = declaration.target;
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ targets.add(target.value);
+ program.inputs.push({ name: name.value, target: target.value, line: token.line });
+ } else {
+ if (keys.has(declaration.key.value)) fail(declaration.key, `Duplicate keyboard code ${declaration.key.value}`);
+ keys.add(declaration.key.value);
+ program.inputs.push({ name: name.value, key: declaration.key.value, line: token.line });
+ }
+ } else if (kind === 'view') {
+ if (views.has(name.value)) fail(name, `Duplicate view ID ${name.value}`);
+ if (views.size >= LIMITS.views) fail(name, 'At most 24 views are allowed');
+ views.add(name.value);
+ } else if (++handlerCount > LIMITS.handlers) fail(token, 'At most 64 handlers are allowed');
+ }
+ for (const declaration of declarations) {
+ if (declaration.target && !views.has(declaration.target.value))
+ fail(declaration.target, `Unknown pointer target ${declaration.target.value}`);
+ }
+ const routedItems = new Set();
+ for (const declaration of declarations) {
+ if (!declaration.routes) continue;
+ const input = inputs.get(declaration.name.value), resolved = program.inputs[input];
+ let type;
+ for (const {target,item:token} of declaration.routes) {
+ if (!views.has(target.value)) fail(target, `Unknown pointer target ${target.value}`);
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ const item = items.get(token.value);
+ if (!item) fail(token, `Unknown item ${token.value}`);
+ if (type && type !== item.type) fail(token, 'Pointer group targets must share one record type');
+ if (routedItems.has(token.value)) fail(token, `Item ${token.value} already has a pointer route`);
+ targets.add(target.value); routedItems.add(token.value); type = item.type;
+ const route = program.pointerTargets.length;
+ if (route >= 24) fail(target, 'At most 24 pointer targets are allowed');
+ program.pointerTargets.push({input,base:item.base,count:item.count});
+ resolved.routes.push({target:target.value, item:token.value, route});
+ }
+ resolved.type = type;
+ }
+ for (const rule of rules.values()) {
+ if (!records.has(rule.type.value)) fail(rule.type, `Unknown record ${rule.type.value}`);
+ if (RESERVED.has(rule.parameter.value)) fail(rule.parameter, `Reserved name ${rule.parameter.value}`);
+ }
+ let pointHandler = false, valueHandler = false;
+ let parameters = null;
+ let parameterPrefix = null;
+ let stack = 0, maxStack = 0;
+ const emit = (op, token, arg = 0, value = 0, delta = 0) => {
+ if (program.instructions.length >= LIMITS.instructions) fail(token, 'At most 512 instructions are allowed');
+ stack += delta;
+ if (stack < 0 || stack > LIMITS.stack) fail(token, 'Expression stack exceeds 64');
+ maxStack = Math.max(maxStack, stack);
+ program.instructions.push({ op, arg, value, line: token.line });
+ };
+ const expression = (node, binding = false) => {
+ const { token } = node;
+ if (node.kind === 'constant') emit(0, token, 0, node.value, 1);
+ else if (node.kind === 'reference') {
+ if (node.name === 'event_value') {
+ if (binding || !valueHandler) fail(token, 'event_value is only available in value change handlers');
+ emit(26, token, 0, 0, 1);
+ } else if (node.name === 'event_x' || node.name === 'event_y') {
+ if (binding || !pointHandler) fail(token, 'event_x and event_y are only available in pointer handlers');
+ emit(node.name === 'event_x' ? 22 : 23, token, 0, 0, 1);
+ } else if (node.name === 'dt') {
+ if (binding) fail(token, 'dt is only available in handlers');
+ emit(2, token, 0, 0, 1);
+ } else {
+ if (parameterPrefix && node.name.startsWith(parameterPrefix) && !parameters.has(node.name))
+ fail(token, `Unknown parameter field ${node.name}`);
+ if (parameters?.has(node.name)) {
+ emit(24, token, parameters.get(node.name), 0, 1);
+ return;
+ }
+ if (!states.has(node.name)) fail(token, `Unknown state ${node.name}`);
+ emit(1, token, states.get(node.name), 0, 1);
+ }
+ } else if (node.kind === 'unary') { expression(node.child, binding); emit(node.op, token); }
+ else if (node.kind === 'binary') {
+ expression(node.left, binding); expression(node.right, binding); emit(node.op, token, 0, 0, -1);
+ } else {
+ for (const arg of node.args) expression(arg, binding);
+ emit(node.op, token, 0, 0, 1 - node.args.length);
+ }
+ };
+ const statements = body => {
+ for (const statement of body) {
+ if (statement.kind === 'assign') {
+ if (parameterPrefix && statement.name.startsWith(parameterPrefix) && !parameters.has(statement.name))
+ fail(statement.token, `Unknown parameter field ${statement.name}`);
+ const parameter = parameters?.get(statement.name);
+ if (parameter === undefined && !states.has(statement.name)) fail(statement.token, `Unknown state ${statement.name}`);
+ expression(statement.expression);
+ emit(parameter === undefined ? 20 : 25, statement.token, parameter === undefined ? states.get(statement.name) : parameter, 0, -1);
+ } else {
+ expression(statement.condition);
+ const branch = program.instructions.length;
+ emit(21, statement.token, 0, 0, -1);
+ statements(statement.body);
+ program.instructions[branch].arg = program.instructions.length;
+ }
+ }
+ };
+ const bodies = new Map();
+ function ruleBody(rule) {
+ if (bodies.has(rule.name.value)) return bodies.get(rule.name.value);
+ parameterPrefix = `${rule.parameter.value}.`;
+ parameters = new Map(records.get(rule.type.value).fields.map((field,index) => [`${rule.parameter.value}.${field.name.value}`,index]));
+ // A shared body may read coordinates; every binding is checked below.
+ pointHandler = true; valueHandler = true; stack = 0;
+ const start = program.instructions.length;
+ statements(rule.body);
+ const length = program.instructions.length - start;
+ const point = program.instructions.slice(start).some(op => op.op === 22 || op.op === 23);
+ parameters = null; parameterPrefix = null;
+ const value = program.instructions.slice(start).some(op => op.op === 26);
+ const body = {start,length,point,value}; bodies.set(rule.name.value,body); return body;
+ }
+ for (const declaration of declarations) {
+ if (declaration.kind === 'handler') {
+ let event = 0;
+ pointHandler = false; valueHandler = false;
+ if (declaration.event.value !== 'frame') {
+ if (!inputs.has(declaration.event.value)) fail(declaration.event, `Unknown input ${declaration.event.value}`);
+ const index = inputs.get(declaration.event.value), edge = declaration.edge.value;
+ pointHandler = Boolean(program.inputs[index].target || program.inputs[index].routes);
+ valueHandler = program.inputs[index].kind === 'value';
+ if (valueHandler !== (edge === 'change')) fail(declaration.edge, 'Value inputs require change; change requires a value input');
+ if (!pointHandler && (edge === 'move' || edge === 'cancel')) fail(declaration.edge, 'move and cancel require a pointer input');
+ event = edge === 'change' ? 33 + index : edge === 'move' ? 17 + index : edge === 'cancel' ? 25 + index : 1 + index * 2 + (edge === 'up' ? 1 : 0);
+ }
+ if (declaration.rule) {
+ const rule = rules.get(declaration.rule.value);
+ const routed = declaration.argument.includes('.');
+ const input = program.inputs[inputs.get(declaration.event.value)];
+ if (routed && (!input?.routes || declaration.argument !== `${declaration.event.value}.target`))
+ fail(declaration.item, 'Use the current pointer group target');
+ const item = routed ? {type:input.type, count:records.get(input.type).fields.length} : items.get(declaration.item.value);
+ if (!rule) fail(declaration.rule, `Unknown rule ${declaration.rule.value}`);
+ if (!item) fail(declaration.item, `Unknown item ${declaration.item.value}`);
+ if (item.type !== rule.type.value) fail(declaration.item, `Rule ${rule.name.value} requires ${rule.type.value}`);
+ const pointer = pointHandler, value = valueHandler;
+ const body = ruleBody(rule);
+ if (body.value && !value) fail(declaration.rule, 'Value-reading rules require a value input');
+ if (body.point && !pointer) fail(declaration.rule, 'Coordinate-reading rules require a pointer input');
+ program.handlers.push({event,start:body.start,length:body.length,line:declaration.token.line,parameterBase:routed ? 255 : item.base,parameterCount:item.count});
+ } else {
+ const start = program.instructions.length;
+ stack = 0; statements(declaration.body);
+ program.handlers.push({ event, start, length: program.instructions.length - start, line: declaration.token.line });
+ }
+ } else if (declaration.kind === 'view') {
+ const view = { id: declaration.name.value, type: declaration.type, line: declaration.token.line, bindings: {} };
+ if (view.type === 'text') view.prefix = declaration.prefix;
+ else view.color = declaration.color;
+ declaration.expressions.forEach((node, index) => {
+ const start = program.instructions.length;
+ stack = 0; expression(node, true);
+ view.bindings[VIEW_FIELDS[view.type][index]] = { start, length: program.instructions.length - start };
+ });
+ program.views.push(view);
+ }
+ }
+ // Unused definitions still receive name/type checking, but reserve no VM body.
+ for (const rule of rules.values()) {
+ if (bodies.has(rule.name.value)) continue;
+ const instructions = program.instructions, previousMax = maxStack;
+ program.instructions = [];
+ ruleBody(rule);
+ program.instructions = instructions; maxStack = previousMax;
+ }
+ program.metrics = { sourceBytes, sourceLines: source === '' ? 0 : source.split('\n').length,
+ states: states.size, inputs: inputs.size, views: views.size,
+ handlers: program.handlers.length, instructions: program.instructions.length, maxStack };
+ return program;
+}
+
+export { LIMITS };
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/core.wasm b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/core.wasm
new file mode 100644
index 0000000..79c50a8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/core.wasm
Binary files differ
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/project.mjs b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/project.mjs
new file mode 100644
index 0000000..861e0fc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/project.mjs
@@ -0,0 +1,47 @@
+import { compile } from './compiler.mjs';
+
+// Two escaped source strings plus up to 32 generated item.field names. A long
+// schema field can appear in every item without repeating in the source text.
+export const MAX_PROJECT_BYTES = (2 * 6 + 32) * 32768 + 8192;
+const encoder = new TextEncoder();
+function sourceText(value, label) {
+ if (typeof value !== 'string' || encoder.encode(value).length > 32768)
+ throw new Error(`${label}: UTF-8 32 KiB 이하의 코드가 필요합니다.`);
+ return value;
+}
+
+// No runtime mutation. Validate every saved value before opening core staging.
+export function validateDocument(document) {
+ if (!document || typeof document !== 'object' || Array.isArray(document) ||
+ document.format !== 'pure-workbench' || document.version !== 2)
+ throw new Error('배치 파일 형식이 맞지 않습니다. pure-workbench version 2가 필요합니다.');
+ const source = sourceText(document.source, '적용된 코드');
+ const draft = sourceText(Object.hasOwn(document, 'draft') ? document.draft : source, '편집 중인 코드');
+ const program = compile(source);
+ if (!Array.isArray(document.states) || document.states.length !== program.states.length)
+ throw new Error('저장된 상태 목록이 적용된 코드와 일치하지 않습니다.');
+ const values = new Map();
+ for (const entry of document.states) {
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry) || typeof entry.name !== 'string' || values.has(entry.name))
+ throw new Error('상태 이름이 잘못됐거나 중복됐습니다.');
+ const value = entry.value === '-0' ? -0 : entry.value;
+ if (typeof value !== 'number' || !Number.isFinite(value)) throw new Error('상태 값은 유한한 숫자여야 합니다.');
+ values.set(entry.name, value);
+ }
+ for (const state of program.states)
+ if (!values.has(state.name)) throw new Error(`저장된 상태가 없습니다: ${state.name}`);
+ return { source, draft, program, values: program.states.map(state => values.get(state.name)) };
+}
+
+export function parseProject(text) {
+ if (typeof text !== 'string' || encoder.encode(text).length > MAX_PROJECT_BYTES)
+ throw new Error('작업 파일이 너무 큽니다.');
+ let project;
+ try { project = JSON.parse(text); } catch { throw new Error('올바른 JSON 파일이 아닙니다.'); }
+ if (!project || typeof project !== 'object' || Array.isArray(project) || project.format !== 'pure-workbench')
+ throw new Error('Pure 작업물 형식이 아닙니다.');
+ if (project.version === 1) sourceText(project.source, '코드');
+ else if (project.version === 2) validateDocument(project);
+ else throw new Error('지원하지 않는 작업 파일 버전입니다.');
+ return project;
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/runtime.mjs b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/runtime.mjs
new file mode 100644
index 0000000..d8d6618
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/sources/prototypes/workbench/web/runtime.mjs
@@ -0,0 +1,350 @@
+import { compile } from './compiler.mjs';
+import { validateDocument } from './project.mjs';
+
+const messages = [
+ '', '실행기의 용량 한도를 넘었습니다.', '실행 정의가 유효하지 않습니다.',
+ '계산 스택의 범위를 벗어났습니다.', '0으로 나눌 수 없습니다.',
+ '계산 결과가 유한한 수의 범위를 벗어났습니다.', '조건 분기 범위가 유효하지 않습니다.',
+ '존재하지 않는 상태를 참조했습니다.', '시간 간격이 유효하지 않습니다.',
+ '정의되지 않은 입력 사건입니다.',
+];
+const sourceLimit = 32768;
+
+function problem(message, line = null, column = null) {
+ return Object.assign(new Error(message), { line, column });
+}
+
+function freezeProgram(value) {
+ if (value && typeof value === 'object') {
+ for (const child of Object.values(value)) freezeProgram(child);
+ Object.freeze(value);
+ }
+ return value;
+}
+
+export async function createRuntime(wasmBytes, evaluationOptions = {}) {
+ if (wasmBytes === undefined) {
+ const response = await fetch(new URL('./core.wasm', import.meta.url), { cache: 'no-store' });
+ if (!response.ok) throw new Error(`실행기를 불러오지 못했습니다 (HTTP ${response.status}).`);
+ wasmBytes = await response.arrayBuffer();
+ }
+ const module = await WebAssembly.compile(wasmBytes);
+ if (WebAssembly.Module.imports(module).length) throw new Error('이 실행기는 호스트 함수 없이 동작해야 합니다.');
+ const { exports: core } = await WebAssembly.instantiate(module, {});
+ if (typeof core.eval_bounded !== 'function' || typeof core.abort_program !== 'function' || typeof core.dispatch_point !== 'function' || typeof core.put_restored_value !== 'function' || typeof core.commit_restored_program !== 'function' || typeof core.bind_handler !== 'function' || typeof core.put_pointer_target !== 'function' || typeof core.bind_target_handler !== 'function' || typeof core.dispatch_target !== 'function' || typeof core.dispatch_value !== 'function')
+ throw new Error('실행기 버전이 맞지 않습니다. 새로고침하거나 core.wasm을 다시 빌드하세요.');
+ core.reset_all();
+ let program = null;
+ let appliedSource = '';
+ let lastEvent = null;
+ // Keep a failed event visible through its release/focus-loss cleanup.
+ // The active program can clear this diagnostic by apply or explicit reset.
+ let lastFailure = null;
+ const held = new Map();
+ const points = new Map();
+ let presenting = false;
+ let bindings = [];
+ let pointRoutes = new Map();
+ // One bounded publication buffer, never exposed to callers. No state mirror.
+ let displayValues = null, displayValid = null;
+ function available() {
+ if (presenting) throw new Error('출력 전달 중에는 실행기를 다시 호출할 수 없습니다.');
+ }
+ let evaluationPolicy = { cacheEntries: 0, historyEntries: 8, workLimit: 2048 };
+
+ function checked(code, line = null) {
+ if (code !== 0) throw problem(messages[code] || `실행기 오류 ${code}`, line);
+ }
+ function inputIndex(name) {
+ const index = program?.inputs.findIndex((input) => input.name === name) ?? -1;
+ if (index < 0) throw new Error(`정의되지 않은 입력: ${name}`);
+ return index;
+ }
+ function dispatch(event, name, phase, source, point = null, value = undefined) {
+ const status = value !== undefined ? core.dispatch_value(event, value) : point ? (point.route === undefined ? core.dispatch_point(event, point.x, point.y)
+ : core.dispatch_target(event, point.route, point.x, point.y)) : core.dispatch(event, event === 0 ? 1 / 60 : 0);
+ const pc = core.info(2) >>> 0;
+ lastEvent = { name, phase, source, status,
+ line: program?.instructions[pc]?.line ?? null, ops: core.info(3) >>> 0 };
+ if (point) { lastEvent.x = point.x; lastEvent.y = point.y; if (point.target) lastEvent.target = point.target; }
+ if (value !== undefined) lastEvent.value = value;
+ if (status) lastFailure = { ...lastEvent };
+ return status;
+ }
+
+ function evaluateDisplay() {
+ core.begin_evaluation(evaluationPolicy.workLimit);
+ if (!bindings.length) return null;
+ displayValues ??= new Float64Array(96);
+ displayValid ??= new Uint8Array(24);
+ let error = null, slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ displayValid[i] = 1;
+ for (const [name, binding] of bindings[i]) {
+ const value = core.eval_bounded(binding.start, binding.length);
+ if (core.evaluation_info(0) === 10) {
+ displayValid.fill(0);
+ return { code: 101, line: view.line,
+ message: '표시 계산의 작업량 한도를 넘었습니다. 한도를 늘리거나 표시식을 줄이세요.' };
+ }
+ if (!Number.isFinite(value) || ((name === 'width' || name === 'height' || name === 'radius') && value < 0)) {
+ error ??= { line: view.line, message: `${view.id}.${name}: 표시할 수 없는 값입니다. 0 나눗셈이나 음수 크기를 확인하세요.` };
+ displayValid[i] = 0;
+ }
+ displayValues[slot++] = value;
+ }
+ }
+ return error;
+ }
+
+ function status(viewError) {
+ const executionError = lastFailure?.status || 0;
+ return {
+ tick: core.info(0) >>> 0, revision: core.info(4) >>> 0,
+ displayError: viewError ? { code: viewError.code || 100, ...viewError } : null,
+ lastError: executionError || (viewError ? viewError.code || 100 : 0),
+ errorMessage: executionError ? messages[executionError] || `실행 오류 ${executionError}` : viewError?.message || '',
+ errorLine: executionError ? lastFailure.line : viewError?.line ?? null,
+ lastOps: core.info(3) >>> 0, successfulEvents: core.info(9) >>> 0,
+ held: [...held.keys()], lastEvent: lastEvent ? { ...lastEvent } : null,
+ lastFailure: lastFailure ? { ...lastFailure } : null,
+ memory: {
+ linearBytes: core.memory.buffer.byteLength,
+ reservedEngineBytes: core.layout(0), programReservedBytes: core.layout(1),
+ instructionBytes: core.layout(2), handlerBytes: core.layout(3),
+ activeIRBytes: core.layout(4), activeStateBytes: core.layout(5),
+ stagingReservedBytes: core.layout(6), evalStackBytes: core.layout(7),
+ pointerTargetBytes: core.layout(8), pointerTargets: core.layout(9),
+ },
+ };
+ }
+
+ function load(next, source, restored = null) {
+ const oldIds = new Map(restored ? [] : program?.states.map((state, index) => [state.name, index]) ?? []);
+ checked(core.begin_program(next.states.length, next.inputs.length));
+ try {
+ for (let index = 0; index < next.states.length; index++) {
+ const state = next.states[index];
+ checked(core.put_state(index, state.initial, oldIds.get(state.name) ?? -1), state.line);
+ if (restored) checked(core.put_restored_value(index, restored[index]), state.line);
+ }
+ for (const op of next.instructions) checked(core.put_instruction(op.op, op.arg, op.value), op.line);
+ for (const target of next.pointerTargets) checked(core.put_pointer_target(target.input, target.base, target.count));
+ for (const [index, handler] of next.handlers.entries()) {
+ checked(core.put_handler(handler.event, handler.start, handler.length), handler.line);
+ if (handler.parameterCount)
+ checked(handler.parameterBase === 255 ? core.bind_target_handler(index, handler.parameterCount)
+ : core.bind_handler(index, handler.parameterBase, handler.parameterCount), handler.line);
+ }
+ checked(restored ? core.commit_restored_program() : core.commit_program());
+ } catch (error) {
+ core.abort_program();
+ throw error;
+ }
+ pointRoutes = new Map(next.inputs.flatMap(input => (input.routes ?? []).map(route => [route.target, route])));
+ program = next;
+ bindings = next.views.map(view => Object.entries(view.bindings));
+ appliedSource = source;
+ lastEvent = null;
+ lastFailure = null;
+ }
+
+ const api = {
+ get currentProgram() { return program; },
+ configureEvaluation({ cacheEntries = evaluationPolicy.cacheEntries,
+ historyEntries = evaluationPolicy.historyEntries, workLimit = evaluationPolicy.workLimit } = {}) {
+ available();
+ for (const [name, value, maximum] of [['cacheEntries', cacheEntries, 32],
+ ['historyEntries', historyEntries, 8], ['workLimit', workLimit, 0xffffffff]]) {
+ if (!Number.isInteger(value) || value < 0 || value > maximum)
+ throw new Error(`${name}: 0~${maximum} 사이의 정수여야 합니다.`);
+ }
+ checked(core.configure_evaluation(cacheEntries, historyEntries));
+ evaluationPolicy = { cacheEntries, historyEntries, workLimit };
+ return { ...evaluationPolicy };
+ },
+ forgetEvaluation(part = 'all') {
+ available();
+ const flags = part === 'all' ? 3 : part === 'values' ? 1 : part === 'history' ? 2 : undefined;
+ if (flags === undefined) throw new Error('삭제할 기록은 values, history, all 중 하나여야 합니다.');
+ core.forget_evaluation(flags);
+ },
+ evaluationStats() {
+ return { ...evaluationPolicy, work: core.evaluation_info(1),
+ instructions: core.evaluation_info(2), cacheHits: core.evaluation_info(3),
+ reservedBytes: core.evaluation_info(6), dedicatedBytes: core.evaluation_info(7),
+ sharedBytes: core.evaluation_info(8), reuseAvailable: Boolean(core.evaluation_info(9)),
+ workspaceTagBytes: core.evaluation_info(10) };
+ },
+ apply(source) {
+ available();
+ if (typeof source !== 'string' || new TextEncoder().encode(source).length > sourceLimit) {
+ throw problem('정의는 UTF-8 기준 32,768바이트 이하의 텍스트여야 합니다.');
+ }
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 적용하세요. 현재 작업은 그대로 유지합니다.');
+ const next = freezeProgram(compile(source));
+ load(next, source);
+ return next;
+ },
+ restoreDocument(document) {
+ available();
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 복원하세요.');
+ const next = validateDocument(document);
+ load(freezeProgram(next.program), next.source, next.values);
+ return { source: next.source, draft: next.draft };
+ },
+ exportDocument(draft = appliedSource) {
+ available();
+ if (!program) throw problem('먼저 코드를 적용하세요.');
+ if (held.size) throw problem('조작을 끝낸 뒤 배치를 저장하세요.');
+ if (lastFailure) throw problem('실행 오류를 해결한 뒤 배치를 저장하세요.');
+ if (typeof draft !== 'string' || new TextEncoder().encode(draft).length > sourceLimit)
+ throw problem('편집 중인 코드는 UTF-8 32 KiB 이하여야 합니다.');
+ return { format: 'pure-workbench', version: 2, source: appliedSource, draft,
+ states: program.states.map((state, i) => {
+ const value = core.get_state(i);
+ return { name: state.name, value: Object.is(value, -0) ? '-0' : value };
+ }) };
+ },
+ reset() {
+ available();
+ held.clear();
+ points.clear();
+ core.reset_state();
+ lastEvent = null;
+ lastFailure = null;
+ },
+ frame(count = 1) {
+ available();
+ if (!Number.isInteger(count) || count < 0 || count > 600) throw new Error('프레임 수는 0~600 사이의 정수여야 합니다.');
+ if (!program) return 0;
+ for (let i = 0; i < count; i++) {
+ const code = dispatch(0, 'frame', 'frame', 'clock');
+ if (code !== 0) return code;
+ }
+ return 0;
+ },
+ down(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name) || new Set();
+ if (sources.has(source)) return 0;
+ const wasDown = sources.size > 0;
+ sources.add(source);
+ held.set(name, sources);
+ return wasDown ? 0 : dispatch(1 + index * 2, name, 'down', source);
+ },
+ up(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name);
+ if (!sources?.delete(source)) return 0;
+ if (sources.size) return 0;
+ held.delete(name);
+ return dispatch(2 + index * 2, name, 'up', source);
+ },
+ change(name, value, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind !== 'value') throw new Error('숫자 값에 연결된 입력이 아닙니다.');
+ if (!Number.isFinite(value)) throw new Error('입력 값은 유한한 숫자여야 합니다.');
+ return dispatch(33 + index, name, 'change', source, null, value);
+ },
+ point(name, phase, x, y, source = 'external', target = undefined) {
+ available();
+ const index = inputIndex(name);
+ const input = program.inputs[index];
+ if (!input.target && !input.routes) throw new Error('포인터에 연결된 입력이 아닙니다.');
+ const route = input.routes ? pointRoutes.get(target) : undefined;
+ if (input.routes && (!route || program.pointerTargets[route.route].input !== index)) throw new Error('포인터 그룹에 연결된 도형 이름이 필요합니다.');
+ if (!input.routes && target !== undefined) throw new Error('단일 포인터 입력에는 대상 인자를 지정하지 않습니다.');
+ const owner = route ? `${name}:${target}` : name;
+ if (!['down', 'move', 'up', 'cancel'].includes(phase)) throw new Error('포인터 단계는 down, move, up, cancel 중 하나여야 합니다.');
+ if (!Number.isFinite(x) || !Number.isFinite(y)) throw new Error('포인터 좌표는 유한한 숫자여야 합니다.');
+ if (typeof source !== 'string' || source.length === 0) throw new Error('포인터 출처 이름이 필요합니다.');
+ let point = points.get(owner);
+ if (phase === 'down') {
+ if (point?.source === source) return 0;
+ if (point) throw new Error('이 입력은 다른 포인터가 사용 중입니다.');
+ point = {name, source, x, y, target, route:route?.route};
+ points.set(owner, point);
+ held.set(owner, new Set([source]));
+ } else {
+ if (!point || point.source !== source) return 0;
+ point.x = x; point.y = y;
+ if (phase === 'up' || phase === 'cancel') { points.delete(owner); held.delete(owner); }
+ }
+ const event = phase === 'move' ? 17 + index : phase === 'cancel' ? 25 + index : 1 + index * 2 + (phase === 'up' ? 1 : 0);
+ return dispatch(event, name, phase, source, point);
+ },
+ releaseAll() {
+ available();
+ let firstError = 0;
+ for (const point of [...points.values()]) {
+ const status = api.point(point.name, 'cancel', point.x, point.y, point.source, point.target);
+ if (!firstError) firstError = status;
+ }
+ for (const [name, sources] of [...held]) {
+ for (const source of [...sources]) {
+ const status = api.up(name, source);
+ if (!firstError) firstError = status;
+ }
+ }
+ return firstError;
+ },
+ exportProject() {
+ return { format: 'pure-workbench', version: 1, source: appliedSource };
+ },
+ // Synchronous trusted output adapter. Callbacks run only after the whole
+ // display has been evaluated. Runtime mutation/reentrant reads are refused.
+ // Exceptions from an adapter propagate; the next call republishes all values.
+ present(target) {
+ available();
+ presenting = true;
+ try {
+ const { begin, state, view, value, end } = target;
+ for (const callback of [begin, state, view, value, end])
+ if (typeof callback !== 'function') throw new TypeError('출력 어댑터 함수가 필요합니다.');
+ const error = evaluateDisplay();
+ begin.call(target, program);
+ for (let i = 0; i < (program?.states.length ?? 0); i++) state.call(target, i, core.get_state(i));
+ let slot = 0, visible = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const valid = Boolean(displayValid[i]);
+ view.call(target, i, valid);
+ for (const [name] of bindings[i]) {
+ if (valid) value.call(target, i, name, displayValues[slot]);
+ slot++;
+ }
+ if (valid) visible++;
+ }
+ end.call(target, visible);
+ return status(error);
+ } finally { presenting = false; }
+ },
+ snapshot() {
+ available();
+ const error = evaluateDisplay();
+ const states = Object.fromEntries((program?.states ?? []).map((state, index) => [state.name, core.get_state(index)]));
+ const views = [];
+ let slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ const rendered = displayValid[i] ? { id: view.id, type: view.type, color: view.color, prefix: view.prefix } : null;
+ for (const [name] of bindings[i]) {
+ if (rendered) rendered[name] = displayValues[slot];
+ slot++;
+ }
+ if (rendered) views.push(rendered);
+ }
+ return { states, views, ...status(error) };
+ },
+ };
+ api.configureEvaluation(evaluationOptions);
+ return Object.freeze(api);
+}
diff --git a/prototypes/connections/results/2026-09-23-field-connections/verification.json b/prototypes/connections/results/2026-09-23-field-connections/verification.json
new file mode 100644
index 0000000..4befb2d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-field-connections/verification.json
@@ -0,0 +1,62 @@
+{
+ "date": "2026-09-23",
+ "scope": "Named boundary fields and data-dependent byte selection; correctness and source lifetimes, not a performance comparison",
+ "compiler": "cc (Debian 14.2.0-19) 14.2.0",
+ "os_page_size_bytes": 16384,
+ "cwd": "prototypes/connections",
+ "native_command": "make check EVIDENCE=results/2026-09-23-field-connections/native.json",
+ "sanitized_command": "make check BUILD=build/sanitized CFLAGS='-std=c17 -O1 -g -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer' EVIDENCE=results/2026-09-23-field-connections/sanitized.json",
+ "core_checks": {
+ "test-flow": {
+ "native": "passed",
+ "asan_ubsan": "passed"
+ },
+ "test-program": {
+ "native": "passed",
+ "asan_ubsan": "passed",
+ "boundary_semantic_comparisons": 3584
+ },
+ "test-fields": {
+ "native": "passed",
+ "asan_ubsan": "passed",
+ "data_boundary_cases": 48
+ },
+ "leak_detection_disabled": false
+ },
+ "unit_binary_sha256": {
+ "build/test-flow": "81bb00a859ffc6dad647159514e80d97ff2897687f6e904610fdd3b70ea30878",
+ "build/test-program": "c15f0f40c50a10b57d456e064d5b64d5a4cbef29bda55495fda0b4648105a866",
+ "build/test-fields": "8b274b9fe8b8c45198f8d536186aeefe0aecd8564f56d903cc4a634624889e00",
+ "build/sanitized/test-flow": "bff35676c65fcb9cd5cf3ee2daa1da33067c6648e436ad62d72ada4609542f93",
+ "build/sanitized/test-program": "e6487158d71ef075771965b4d80c7c116c689174a7cd2dee4f9e5a465def4325",
+ "build/sanitized/test-fields": "30852cde86252c52ff244f544b847ef05683ab0b33ed4dd4a134fe5fdd49a940"
+ },
+ "integration_scenarios_each": 28,
+ "previous_scenarios": 22,
+ "field_scenarios": 6,
+ "source_snapshots": "sources/",
+ "source_hashes_equal": true,
+ "source_snapshots_match_records": true,
+ "final_binaries_match_records": true,
+ "prepared_connections_equal": true,
+ "field_connections_equal": true,
+ "prepared_program_bytes": 648,
+ "previous_prepared_program_bytes": 112,
+ "native_dynamic_dependencies_ldd": [
+ "\tlinux-vdso.so.1 (0x00007fff973d8000)",
+ "\tlibc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00007fff97190000)",
+ "\t/lib/ld-linux-aarch64.so.1 (0x00007fff973a0000)"
+ ],
+ "limitations": [
+ "Declared boundary layouts are not a universal storage schema or application object model",
+ "Only u32le, fixed bytes, and a final variable byte field; no general arithmetic or schema version negotiation",
+ "Dynamic ranges operate on PUT input; GET numeric-dependent ranges are rejected",
+ "One storage effect per handler, no read-modify-write, branches or feedback loops",
+ "Program always reserves room for eight dynamic range steps, including programs that use none",
+ "Source receive allocation remains fully retained/charged even when a small selection is returned",
+ "Server byte fields do not validate UTF-8; the example Python client preserves code-point boundaries",
+ "Logical payload bounds exclude mapping pages, page cache, disk, OS sockets and client allocations",
+ "Synchronous storage can delay other connections and timeout enforcement",
+ "Linux AArch64 only; macOS, real power loss, and large-service performance not tested"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/README.md b/prototypes/connections/results/2026-09-23-native-connections/README.md
new file mode 100644
index 0000000..0e4f385
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/README.md
@@ -0,0 +1,26 @@
+# 018 검증 자료
+
+> 이 SQLite 구현은 [019](../2026-09-23-byte-storage/README.md)의 SQL 없는 경로로 교체했다.
+> 이 디렉터리의 원자료와 소스 사본은 당시 결과를 보존한다. 현재 작업 트리에서 실행하면
+> 새 구현을 검사하므로, 당시 구현의 재현에는 `sources/`의 파일들을 별도 작업 트리에 사용한다.
+
+이 디렉터리는 실제 루프백 TCP·SQLite·기존 Workbench CLI를 연결한 기능·수명 검사 자료다.
+속도·처리량·전체 RSS 비교는 수행하지 않았다.
+
+- [native.json](native.json): 일반 빌드의 15개 통합 시나리오, 종료 시 자원 수, 환경과 소스·실행 파일 해시.
+- [sanitized.json](sanitized.json): ASan·UBSan 빌드에서 같은 시나리오. 누수 검사를 비활성화하지 않았다.
+- [verification.json](verification.json): 빌드·실행 명령, 코어·CLI 결과와 파일 일치 확인.
+
+서버가 만든 임시 DB에 실제 작성물 배치를 저장하고 새 CLI에서 복원했다. 객체 버전의
+충돌과 64비트 정밀도, 저장 오류, DB 잠금, 읽는 중 다른 커밋, 부분 입력·출력, 연결 종료,
+한도와 기한을 검사한다. 큰 본문은 부분 전송·한도 거절을 발생시키기 위한 정확성 fixture다.
+작업량을 크게 만들어 성능을 주장하는 벤치마크가 아니다.
+
+`retained_payload_bytes`는 수신 할당과 빌린 DB 결과의 길이 합이다. 실제 SQLite·OS·전체
+프로세스 메모리는 포함하지 않는다. `ingress_prefix_copy_bytes`는 서버가 직접 복사한
+수신 접두부만 센다. 전송 배치에 따라 값이 바뀔 수 있어 두 빌드의 시간·복사 효율 비교에 쓰지 않는다.
+
+재현은 [구현 README](../../README.md)의 `make check` 명령을 따른다. `EVIDENCE=/새/경로.json`을
+추가하면 새 증거 파일을 저장한다. 이미 있는 파일을 덮어쓰지 않는다. 실제 소켓·자식 프로세스·
+LeakSanitizer가 제한된 환경에서는 권한이 필요하다. 이 실행에서는 샌드박스가 해당 기능을
+차단해 승인된 샌드박스 밖의 로컬 검사로 확인했다. 외부 네트워크 서비스는 사용하지 않았다.
diff --git a/prototypes/connections/results/2026-09-23-native-connections/native.json b/prototypes/connections/results/2026-09-23-native-connections/native.json
new file mode 100644
index 0000000..5f7e53f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/native.json
@@ -0,0 +1,98 @@
+{
+ "kind": "native-path-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "busy and injected DB failure do not acknowledge or change data",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines"
+ ],
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 38,
+ "commits": 11,
+ "gets": 13,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 31,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115411,
+ "server_structure_bytes": 39112
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39112
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39112
+ }
+ ],
+ "sqlite_runtime": "3.46.1",
+ "binary_sha256": "ff1c2d09d940d9f9a9170e6fea894aee9926e98f04567d389a0c00d5ddf4c7f7",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "b0b50b0d85900b26257aac68177951e8319fd5482a1fcff4c91722f7ba30f74c",
+ "prototypes/connections/store.h": "07d347ae872a3d618dda1697b01bb32abee44b3451472a1b2225963085c11cf2",
+ "prototypes/connections/server.c": "3ff9d9497ad2a8ece657b50af9f8e6e564a974e6bbe3542f0ebe32279883d219",
+ "prototypes/connections/check.py": "be75db13ab2f11d3dd0e064aaa271bf28145aef11423e8ed536c755dcf96eaac",
+ "prototypes/connections/test-flow.c": "17472b90ebd3067b43a0cd06fb571111206b2025a2bd552b1602c3189f17ce0b",
+ "prototypes/connections/Makefile": "6c05917782adf733d31d9bfd42ee8f41b05fe94d965c362577189d6849b61e3e",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sanitized.json b/prototypes/connections/results/2026-09-23-native-connections/sanitized.json
new file mode 100644
index 0000000..c391070
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sanitized.json
@@ -0,0 +1,98 @@
+{
+ "kind": "native-path-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "busy and injected DB failure do not acknowledge or change data",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines"
+ ],
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 38,
+ "commits": 11,
+ "gets": 13,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 31,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115411,
+ "server_structure_bytes": 39112
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39112
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39112
+ }
+ ],
+ "sqlite_runtime": "3.46.1",
+ "binary_sha256": "2e3bb0802082637989041063c2bc34ad6c9a072abc257d7adefdc65cba315298",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "b0b50b0d85900b26257aac68177951e8319fd5482a1fcff4c91722f7ba30f74c",
+ "prototypes/connections/store.h": "07d347ae872a3d618dda1697b01bb32abee44b3451472a1b2225963085c11cf2",
+ "prototypes/connections/server.c": "3ff9d9497ad2a8ece657b50af9f8e6e564a974e6bbe3542f0ebe32279883d219",
+ "prototypes/connections/check.py": "be75db13ab2f11d3dd0e064aaa271bf28145aef11423e8ed536c755dcf96eaac",
+ "prototypes/connections/test-flow.c": "17472b90ebd3067b43a0cd06fb571111206b2025a2bd552b1602c3189f17ce0b",
+ "prototypes/connections/Makefile": "6c05917782adf733d31d9bfd42ee8f41b05fe94d965c362577189d6849b61e3e",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/Makefile b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/Makefile
new file mode 100644
index 0000000..c520aa5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/Makefile
@@ -0,0 +1,22 @@
+CC ?= cc
+CPPFLAGS += $(shell pkg-config --cflags sqlite3)
+CFLAGS ?= -O2 -g
+CFLAGS += -std=c17 -Wall -Wextra -Wpedantic -Werror
+LDLIBS += $(shell pkg-config --libs sqlite3)
+BUILD ?= build
+
+.PHONY: all check
+all: $(BUILD)/pure-connections
+
+$(BUILD):
+ mkdir -p $@
+
+$(BUILD)/pure-connections: server.c store.c flow.c store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) server.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-flow: test-flow.c store.c flow.c store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-flow.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+check: $(BUILD)/test-flow $(BUILD)/pure-connections
+ $(BUILD)/test-flow
+ python3 check.py --server $(BUILD)/pure-connections $(if $(EVIDENCE),--output "$(EVIDENCE)")
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/check.py b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/check.py
new file mode 100644
index 0000000..c19fcaa
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/check.py
@@ -0,0 +1,306 @@
+#!/usr/bin/env python3
+"""Exercise the real local TCP/SQLite path and the existing workbench CLI."""
+import argparse
+from contextlib import contextmanager
+import hashlib
+import http.client
+import json
+import platform
+from pathlib import Path
+import select
+import socket
+import sqlite3
+import struct
+import subprocess
+import tempfile
+import time
+
+ROOT = Path(__file__).resolve().parent
+WORKBENCH = ROOT.parent / 'workbench'
+OBJECT_LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+class Server:
+ def __init__(self, binary, database, budget=4 * 1024 * 1024, timeout=5000):
+ self.process = subprocess.Popen([str(binary), '--db', str(database), '--port', '0',
+ '--budget', str(budget), '--timeout-ms', str(timeout), '--send-buffer', '4096'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
+ if not select.select([self.process.stdout], [], [], 15)[0]:
+ self.process.kill()
+ raise AssertionError('server readiness timed out')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.ready = json.loads(line)
+ self.port = self.ready['port']
+ self.stats = None
+
+ def close(self):
+ if self.process.poll() is None:
+ self.process.terminate()
+ try:
+ stdout, stderr = self.process.communicate(timeout=10)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.process.communicate()
+ raise
+ assert self.process.returncode == 0, (stdout, stderr)
+ self.stats = json.loads(stderr)
+ assert self.stats['active'] == self.stats['retained_payload_bytes'] == 0
+ assert self.stats['peak_retained_payload_bytes'] <= self.stats['payload_budget']
+ assert self.stats['peak_connections'] <= 8
+
+
+@contextmanager
+def serving(*args, **kwargs):
+ server = Server(*args, **kwargs)
+ try:
+ yield server
+ finally:
+ server.close()
+
+
+def rpc(server, method, key, body=b'', expected=None):
+ headers = {'Content-Length': str(len(body))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = '*' if expected == 0 else f'"{expected}"'
+ connection = http.client.HTTPConnection('127.0.0.1', server.port, timeout=8)
+ try:
+ connection.request(method, f'/objects/{key}', body, headers)
+ response = connection.getresponse()
+ return response.status, dict(response.getheaders()), response.read()
+ finally:
+ connection.close()
+
+
+def wire(server, request, chunks=None):
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ if chunks:
+ for chunk in chunks:
+ sock.sendall(chunk)
+ else:
+ sock.sendall(request)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ return response.status, dict(response.getheaders()), response.read()
+
+
+def header(method, key, size=0, condition=b''):
+ return (f'{method} /objects/{key} HTTP/1.1\r\nHost: localhost\r\n'
+ f'Content-Length: {size}\r\n'.encode() + condition + b'\r\n')
+
+
+def cli(server, commands, source=None, expected_code=0):
+ result = subprocess.run(['node', str(WORKBENCH / 'cli.mjs'), *([str(source)] if source else [])],
+ input=commands.replace('$URL', f'http://127.0.0.1:{server.port}'), text=True,
+ capture_output=True, timeout=30)
+ assert result.returncode == expected_code, (result.stdout, result.stderr)
+ return [json.loads(line) for line in result.stdout.splitlines()], result.stderr
+
+
+def check(binary, directory):
+ database = directory / 'objects.db'
+ checks, records = [], []
+ with serving(binary, database) as server:
+ assert rpc(server, 'GET', 'absent')[0] == 404
+ payload = b'\x00\xffbinary\r\n\r\n' + bytes(range(256)) * 41
+ request = header('PUT', 'binary', len(payload), b'If-None-Match: *\r\n') + payload
+ status, headers, _ = wire(server, request, [request[:7], request[7:51], request[51:57], request[57:]])
+ assert status == 200 and headers['ETag'] == '"1"'
+ assert rpc(server, 'GET', 'binary')[2] == payload
+ checks.append('fragmented request and binary bytes round trip')
+ assert rpc(server, 'PUT', 'binary', b'new', 0)[0] == 412
+ assert rpc(server, 'PUT', 'binary', b'new', 1)[0] == 200
+ assert rpc(server, 'PUT', 'binary', b'stale', 1)[0] == 412
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('conditional create and stale revision preserve committed bytes')
+
+ lock = sqlite3.connect(database, timeout=0)
+ lock.execute('BEGIN IMMEDIATE')
+ assert rpc(server, 'PUT', 'binary', b'blocked', 2)[0] == 503
+ lock.rollback()
+ lock.execute("CREATE TRIGGER reject_write BEFORE UPDATE ON pure_objects BEGIN SELECT RAISE(ABORT,'test failure'); END")
+ lock.commit()
+ assert rpc(server, 'PUT', 'binary', b'failure', 2)[0] == 500
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ lock.execute('DROP TRIGGER reject_write')
+ lock.commit()
+ lock.close()
+ checks.append('busy and injected DB failure do not acknowledge or change data')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'incomplete', 100, b'If-None-Match: *\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ sock.close()
+ assert rpc(server, 'GET', 'incomplete')[0] == 404
+ checks.append('incomplete request never commits and releases its allocation')
+
+ # Force genuine partial socket sends. A write on another connection must
+ # not alter the SQLite row whose bytes are still being transmitted.
+ large = bytes(range(256)) * 4096
+ assert rpc(server, 'PUT', 'large', large, 0)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.getheader('ETag') == '"1"'
+ assert response.read(17) == large[:17]
+ assert rpc(server, 'PUT', 'large', b'changed', 1)[0] == 200
+ assert response.read() == large[17:]
+ sock.close()
+ assert rpc(server, 'GET', 'large')[2] == b'changed'
+ checks.append('borrowed read remains the same snapshot during another commit')
+
+ assert rpc(server, 'PUT', 'large', large, 2)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ assert sock.recv(1)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ sock.close()
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('receiver reset aborts an outstanding borrowed transfer')
+
+ assert wire(server, header('PUT', 'too_large', OBJECT_LIMIT + 1, b'If-None-Match: *\r\n'))[0] == 413
+ malformed = [
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nContent-Length: 1\r\nContent-Length: 1\r\nIf-None-Match: *\r\n\r\nx',
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n',
+ b'GET /objects/bad HTTP/1.1\r\nHost: x\x00hidden\r\n\r\n',
+ ]
+ for request in malformed:
+ assert wire(server, request)[0] == 400
+ assert rpc(server, 'GET', 'bad')[0] == 404
+ checks.append('unsupported framing and oversized payload are rejected before effects')
+
+ # Existing authoring path: define, manipulate, save remotely, reconstruct
+ # in a fresh runtime. No fabricated project fixture or mock database.
+ source = WORKBENCH / 'examples' / 'direct.pure'
+ saved = directory / 'restored.json'
+ lines, _ = cli(server, 'point drag down 80 180\npoint drag move 210 210\npoint drag up 210 210\n'
+ 'connect $URL authored\npush 0\nquit\n', source)
+ snapshots = [line for line in lines if 'states' in line]
+ assert snapshots
+ expected_states = snapshots[-1]['states']
+ assert expected_states['x'] == 210 and expected_states['y'] == 190 and expected_states['dragging'] == 0
+ lines, _ = cli(server, f'connect $URL authored\npull\nsave-project {saved}\nquit\n')
+ assert [line for line in lines if 'states' in line][-1]['states'] == expected_states
+ document = json.loads(saved.read_text())
+ assert document['version'] == 2 and document['source'] == source.read_text()
+ lines, error = cli(server, 'connect $URL authored\npush 0\nquit\n', source, 1)
+ assert '412' in error
+ checks.append('existing workbench manipulation restores in a fresh runtime and reports conflict')
+
+ assert rpc(server, 'PUT', 'invalid_project', b'{"format":"pure-workbench","version":2,"source":"state x=1","states":[]}', 0)[0] == 200
+ lines, error = cli(server, 'show\nconnect $URL invalid_project\npull\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and error
+ lines, error = cli(server, 'point drag down 90 170\nconnect $URL authored\npull\npush\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and states[-1]['dragging'] == 1
+ assert len(error.strip().splitlines()) == 2
+ checks.append('invalid or non-idle restore preserves local state and does not adopt remote revision')
+
+ assert rpc(server, 'PUT', 'wide_revision', rpc_bytes(saved), 0)[0] == 200
+ with sqlite3.connect(database) as database_connection:
+ database_connection.execute('UPDATE pure_objects SET revision=? WHERE key=?', (9007199254740993, 'wide_revision'))
+ lines, _ = cli(server, 'connect $URL wide_revision\npull\npush\nquit\n')
+ revisions = [line['revision'] for line in lines if 'remote' in line and 'revision' in line]
+ assert revisions == ['9007199254740993', '9007199254740994']
+ checks.append('revision above JavaScript safe integer round trips without numeric coercion')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'unread_ack', 4, b'If-None-Match: *\r\n') + b'done')
+ try:
+ deadline = time.monotonic() + 3
+ while True:
+ with sqlite3.connect(database) as database_connection:
+ committed = database_connection.execute('SELECT body FROM pure_objects WHERE key=?', ('unread_ack',)).fetchone()
+ if committed:
+ assert committed[0] == b'done'
+ break
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ finally:
+ sock.close() # Client never consumes the successful response.
+ assert rpc(server, 'PUT', 'unread_ack', b'again', 0)[0] == 412
+ assert rpc(server, 'GET', 'unread_ack')[2] == b'done'
+ checks.append('unread acknowledgment does not undo commit or permit a stale retry')
+
+ # A disconnect after commit can hide the ACK; retries remain conditional.
+ assert rpc(server, 'PUT', 'empty', b'', 0)[0] == 200
+ assert rpc(server, 'GET', 'empty')[2] == b''
+ checks.append('empty body has a valid lifetime and stored revision')
+ records.append(server.stats)
+
+ with serving(binary, database) as restarted:
+ assert rpc(restarted, 'GET', 'binary')[2] == b'new'
+ assert rpc(restarted, 'GET', 'authored')[2] == rpc_bytes(saved)
+ checks.append('committed authoring state survives process restart')
+ records.append(restarted.stats)
+
+ # Fixed small payload budget is an admission test, not a throughput workload.
+ with serving(binary, database, budget=1024 * 1024, timeout=1200) as limited:
+ sock = socket.create_connection(('127.0.0.1', limited.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200
+ assert response.read(1) == large[:1]
+ status, headers, _ = rpc(limited, 'GET', 'large')
+ assert status == 503 and headers['X-Pure-Error'] == 'payload_budget'
+ # Leave the first receiver stalled until the absolute connection deadline.
+ time.sleep(1.4)
+ assert rpc(limited, 'GET', 'binary')[2] == b'new'
+ response.close()
+ sock.close()
+ checks.append('slow consumer retains its lease; budget rejects another; deadline releases it')
+
+ idle = [socket.create_connection(('127.0.0.1', limited.port), timeout=8) for _ in range(8)]
+ try:
+ for s in idle:
+ s.sendall(b'G')
+ for s in idle:
+ assert s.recv(1) == b''
+ finally:
+ for s in idle:
+ s.close()
+ assert rpc(limited, 'GET', 'binary')[0] == 200
+ checks.append('connection slots stay bounded and recover after header deadlines')
+ assert limited.stats['budget_rejections'] >= 1 and limited.stats['expired'] >= 9
+ records.append(limited.stats)
+ return {'kind': 'native-path-correctness-not-performance', 'checks': checks,
+ 'server_runs': records, 'sqlite_runtime': server.ready['sqlite']}
+
+
+def rpc_bytes(path):
+ # CLI export is pretty JSON; wire export is compact JSON with the same model.
+ return json.dumps(json.loads(path.read_text()), ensure_ascii=False, separators=(',', ':')).encode()
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path, default=ROOT / 'build/pure-connections')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ binary = args.server.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-connections-check-') as temporary:
+ result = check(binary, Path(temporary))
+ result['binary_sha256'] = hashlib.sha256(binary.read_bytes()).hexdigest()
+ result['environment'] = {'platform': platform.platform(), 'machine': platform.machine(),
+ 'python': platform.python_version(), 'node': subprocess.check_output(['node', '--version'], text=True).strip()}
+ result['source_sha256'] = {str(path.relative_to(ROOT.parent.parent)): hashlib.sha256(path.read_bytes()).hexdigest()
+ for path in [*(ROOT / name for name in ('flow.c', 'flow.h', 'store.c', 'store.h', 'server.c', 'check.py', 'test-flow.c', 'Makefile')),
+ *(WORKBENCH / name for name in ('remote.mjs', 'cli.mjs', 'web/core.wasm', 'web/runtime.mjs',
+ 'web/compiler.mjs', 'web/project.mjs', 'examples/direct.pure'))]}
+ output = json.dumps(result, ensure_ascii=False, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/flow.c b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/flow.c
new file mode 100644
index 0000000..1070c70
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/flow.c
@@ -0,0 +1,41 @@
+#include "flow.h"
+#include <assert.h>
+
+void pure_transfer_abort(PureTransfer *t) {
+ if (!t->active) return;
+ PureRelease release = t->release;
+ void *owner = t->owner;
+ *t = (PureTransfer){0};
+ if (release) release(owner);
+}
+
+static void advance(PureTransfer *t) {
+ while (t->active && t->part < 2 && t->offset == t->spans[t->part].size) {
+ t->part++;
+ t->offset = 0;
+ }
+ if (t->active && t->part == 2) pure_transfer_abort(t);
+}
+
+void pure_transfer_init(PureTransfer *t, PureSpan header, PureSpan body,
+ void *owner, PureRelease release) {
+ assert(!t->active);
+ assert((!header.size || header.data) && (!body.size || body.data));
+ *t = (PureTransfer){.spans = {header, body}, .owner = owner,
+ .release = release, .active = true};
+ advance(t);
+}
+
+PureSpan pure_transfer_next(const PureTransfer *t, size_t limit) {
+ if (!t->active) return (PureSpan){0};
+ PureSpan span = t->spans[t->part];
+ size_t remaining = span.size - t->offset;
+ return (PureSpan){span.data + t->offset, remaining < limit ? remaining : limit};
+}
+
+bool pure_transfer_consume(PureTransfer *t, size_t bytes) {
+ if (!t->active || bytes > t->spans[t->part].size - t->offset) return false;
+ t->offset += bytes;
+ advance(t);
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/flow.h b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/flow.h
new file mode 100644
index 0000000..6e27c58
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/flow.h
@@ -0,0 +1,25 @@
+#ifndef PURE_FLOW_H
+#define PURE_FLOW_H
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef struct { const unsigned char *data; size_t size; } PureSpan;
+typedef void (*PureRelease)(void *owner);
+
+/* A borrowed body stays alive until every byte is consumed or the transfer is
+ * aborted. A successful send() consumes bytes; peer receipt is a separate fact.
+ * Single owner thread; callbacks must not reenter or reuse this transfer. */
+typedef struct {
+ PureSpan spans[2];
+ size_t part, offset;
+ void *owner;
+ PureRelease release;
+ bool active;
+} PureTransfer;
+
+void pure_transfer_init(PureTransfer *, PureSpan header, PureSpan body,
+ void *owner, PureRelease);
+PureSpan pure_transfer_next(const PureTransfer *, size_t limit);
+bool pure_transfer_consume(PureTransfer *, size_t bytes);
+void pure_transfer_abort(PureTransfer *);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/server.c b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/server.c
new file mode 100644
index 0000000..8f7b1ed
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/server.c
@@ -0,0 +1,346 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+enum { SLOTS = 8, HEADER_LIMIT = 4096, CHUNK = 65536 };
+typedef enum { READING_HEADER, READING_BODY, WRITING } Phase;
+typedef struct Server Server;
+typedef struct {
+ int fd;
+ Phase phase;
+ uint64_t deadline;
+ char request[HEADER_LIMIT + 1], response[512], key[65];
+ size_t header_size, body_size, received, charged;
+ unsigned char *body;
+ bool put;
+ int64_t expected;
+ PureStoredView stored;
+ PureTransfer transfer;
+ Server *server;
+} Connection;
+struct Server {
+ const char *path;
+ size_t budget, retained, peak_retained, active, peak_active;
+ uint64_t accepted, commits, gets, conflicts, budget_rejections, expired;
+ uint64_t releases, prefix_copy_bytes, borrowed_output_bytes;
+ uint64_t timeout_ms;
+ int send_buffer;
+ Connection connections[SLOTS];
+};
+static volatile sig_atomic_t stopping;
+static void stop_server(int sig) { (void)sig; stopping = 1; }
+
+static uint64_t now_ms(void) {
+ struct timespec t;
+ if (clock_gettime(CLOCK_MONOTONIC, &t)) abort();
+ return (uint64_t)t.tv_sec * 1000 + (uint64_t)t.tv_nsec / 1000000;
+}
+
+static bool number(const char *text, uint64_t maximum, uint64_t *value) {
+ if (!*text) return false;
+ uint64_t n = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > maximum || n > (maximum - digit) / 10) return false;
+ n = n * 10 + digit;
+ }
+ *value = n;
+ return true;
+}
+
+static void release_payload(void *owner) {
+ Connection *c = owner;
+ bool owned = c->body || c->stored.db || c->charged;
+ pure_store_release(&c->stored);
+ free(c->body);
+ c->body = NULL;
+ assert(c->charged <= c->server->retained);
+ c->server->retained -= c->charged;
+ c->charged = 0;
+ if (owned) ++c->server->releases;
+}
+
+static void close_connection(Connection *c) {
+ if (c->fd < 0) return;
+ if (c->transfer.active) pure_transfer_abort(&c->transfer);
+ else if (c->body || c->stored.db || c->charged) release_payload(c);
+ close(c->fd);
+ --c->server->active;
+ *c = (Connection){.fd = -1};
+}
+
+static bool charge(Connection *c, size_t size) {
+ Server *s = c->server;
+ if (size > s->budget - s->retained) { ++s->budget_rejections; return false; }
+ s->retained += size;
+ c->charged += size;
+ if (s->retained > s->peak_retained) s->peak_retained = s->retained;
+ return true;
+}
+
+static void respond(Connection *c, int status, const char *reason, const char *error,
+ int64_t revision, PureSpan body) {
+ char tag[80] = "";
+ if (revision > 0) snprintf(tag, sizeof(tag), "ETag: \"%" PRId64 "\"\r\n", revision);
+ int length = snprintf(c->response, sizeof(c->response),
+ "HTTP/1.1 %d %s\r\nContent-Length: %zu\r\nConnection: close\r\n"
+ "Content-Type: application/octet-stream\r\nCache-Control: no-store\r\n"
+ "X-Pure-Error: %s\r\n%s\r\n", status, reason, body.size, error, tag);
+ assert(length > 0 && (size_t)length < sizeof(c->response));
+ c->phase = WRITING;
+ pure_transfer_init(&c->transfer,
+ (PureSpan){(const unsigned char *)c->response, (size_t)length}, body, c, release_payload);
+}
+
+static void fail(Connection *c, int status, const char *reason, const char *error) {
+ /* No outstanding backend access on the owner thread at this point. */
+ if (c->body || c->stored.db || c->charged) release_payload(c);
+ respond(c, status, reason, error, 0, (PureSpan){0});
+}
+
+static void run_request(Connection *c) {
+ PureResult result;
+ int64_t revision = 0;
+ if (c->put) {
+ result = pure_store_put(c->server->path, c->key, c->expected,
+ (PureSpan){c->body, c->body_size}, &revision);
+ /* Binding has been finalized, including the failure path. */
+ release_payload(c);
+ if (result == PURE_OK) ++c->server->commits;
+ } else {
+ result = pure_store_get(c->server->path, c->key,
+ c->server->budget - c->server->retained, &c->stored);
+ if (result == PURE_OK) {
+ if (!charge(c, c->stored.body.size)) abort(); /* Same owner thread. */
+ revision = c->stored.revision;
+ ++c->server->gets;
+ c->server->borrowed_output_bytes += c->stored.body.size;
+ } else if (result == PURE_BUDGET) ++c->server->budget_rejections;
+ }
+ switch (result) {
+ case PURE_OK: respond(c, 200, "OK", "none", revision, c->stored.body); break;
+ case PURE_NOT_FOUND: fail(c, 404, "Not Found", "not_found"); break;
+ case PURE_CONFLICT:
+ ++c->server->conflicts;
+ respond(c, 412, "Precondition Failed", "conflict", revision, (PureSpan){0}); break;
+ case PURE_BUSY: fail(c, 503, "Service Unavailable", "db_busy"); break;
+ case PURE_BUDGET: fail(c, 503, "Service Unavailable", "payload_budget"); break;
+ case PURE_LIMIT: fail(c, 413, "Content Too Large", "limit"); break;
+ default: fail(c, 500, "Internal Server Error", "storage"); break;
+ }
+}
+
+/* Deliberately bounded HTTP/1.1 subset: one GET/PUT, Content-Length, close.
+ * No transfer coding, pipelining, trailers, Expect, URL decoding, or proxying. */
+static bool parse_header(Connection *c, size_t end) {
+ for (size_t i = 0; i < end; ++i) {
+ unsigned char b = (unsigned char)c->request[i];
+ if ((b < 32 && b != '\r' && b != '\n' && b != '\t') || b == 127) return false;
+ }
+ char *line = c->request, *next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *path = strchr(line, ' ');
+ if (!path) return false;
+ *path++ = 0;
+ if (strcmp(line, "PUT") == 0) c->put = true;
+ else if (strcmp(line, "GET") != 0) return false;
+ char *version = strchr(path, ' ');
+ if (!version) return false;
+ *version++ = 0;
+ if (strcmp(version, "HTTP/1.1") || strncmp(path, "/objects/", 9)) return false;
+ const char *key = path + 9;
+ size_t key_size = strlen(key);
+ if (!key_size || key_size > 64) return false;
+ for (size_t i = 0; i < key_size; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ memcpy(c->key, key, key_size + 1);
+ bool length_seen = false, condition_seen = false, host_seen = false;
+ line = next + 2;
+ while (*line != '\r') {
+ next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *value = strchr(line, ':');
+ if (!value || value == line) return false;
+ *value++ = 0;
+ for (char *p = line; *p; ++p)
+ if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') || *p == '-')) return false;
+ while (*value == ' ' || *value == '\t') ++value;
+ char *tail = value + strlen(value);
+ while (tail > value && (tail[-1] == ' ' || tail[-1] == '\t')) *--tail = 0;
+ if (strchr(value, '\r') || strchr(value, '\n')) return false;
+ uint64_t n;
+ if (!strcasecmp(line, "Content-Length")) {
+ if (length_seen || !number(value, SIZE_MAX, &n)) return false;
+ length_seen = true;
+ c->body_size = (size_t)n;
+ } else if (!strcasecmp(line, "Host")) {
+ if (host_seen || !*value) return false;
+ host_seen = true;
+ } else if (!strcasecmp(line, "If-Match")) {
+ if (condition_seen || tail - value < 3 || *value != '"' || tail[-1] != '"') return false;
+ tail[-1] = 0;
+ if (!number(value + 1, INT64_MAX, &n) || !n) return false;
+ c->expected = (int64_t)n;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "If-None-Match")) {
+ if (condition_seen || strcmp(value, "*")) return false;
+ c->expected = 0;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "Transfer-Encoding") || !strcasecmp(line, "Expect")) return false;
+ line = next + 2;
+ }
+ return host_seen && (c->put ? length_seen && condition_seen : !condition_seen && c->body_size == 0);
+}
+
+static void read_connection(Connection *c) {
+ if (c->phase == READING_HEADER) {
+ ssize_t n = recv(c->fd, c->request + c->header_size, HEADER_LIMIT - c->header_size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->header_size += (size_t)n;
+ c->request[c->header_size] = 0;
+ /* Scan by byte count, so embedded NUL cannot hide a terminator. */
+ size_t end = 0;
+ for (size_t i = 3; i < c->header_size; ++i)
+ if (!memcmp(c->request + i - 3, "\r\n\r\n", 4)) { end = i + 1; break; }
+ if (!end) {
+ if (c->header_size == HEADER_LIMIT) fail(c, 431, "Request Header Fields Too Large", "headers");
+ return;
+ }
+ size_t prefix = c->header_size - end;
+ if (!parse_header(c, end)) { fail(c, 400, "Bad Request", "request"); return; }
+ if (c->body_size > PURE_OBJECT_LIMIT) { fail(c, 413, "Content Too Large", "limit"); return; }
+ if (prefix > c->body_size) { fail(c, 400, "Bad Request", "extra_body"); return; }
+ if (!c->put) { run_request(c); return; }
+ if (!charge(c, c->body_size)) { fail(c, 503, "Service Unavailable", "payload_budget"); return; }
+ c->body = malloc(c->body_size ? c->body_size : 1);
+ if (!c->body) { fail(c, 503, "Service Unavailable", "allocation"); return; }
+ if (prefix) memcpy(c->body, c->request + end, prefix);
+ c->server->prefix_copy_bytes += prefix;
+ c->received = prefix;
+ c->phase = READING_BODY;
+ if (c->received == c->body_size) run_request(c);
+ } else {
+ size_t remaining = c->body_size - c->received;
+ ssize_t n = recv(c->fd, c->body + c->received, remaining < CHUNK ? remaining : CHUNK, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->received += (size_t)n;
+ if (c->received == c->body_size) run_request(c);
+ }
+}
+
+static void write_connection(Connection *c) {
+ PureSpan span = pure_transfer_next(&c->transfer, CHUNK);
+ ssize_t n = send(c->fd, span.data, span.size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ if (!pure_transfer_consume(&c->transfer, (size_t)n)) abort();
+ if (!c->transfer.active) close_connection(c);
+}
+
+static bool nonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
+}
+
+int main(int argc, char **argv) {
+ Server server = {.budget = 4u * 1024u * 1024u, .timeout_ms = 10000};
+ unsigned port = 8767;
+ for (int i = 1; i < argc; i += 2) {
+ if (i + 1 == argc) goto usage;
+ uint64_t value;
+ if (!strcmp(argv[i], "--db")) server.path = argv[i + 1];
+ else if (!strcmp(argv[i], "--port") && number(argv[i + 1], 65535, &value)) port = (unsigned)value;
+ else if (!strcmp(argv[i], "--budget") && number(argv[i + 1], SIZE_MAX, &value) && value) server.budget = (size_t)value;
+ else if (!strcmp(argv[i], "--timeout-ms") && number(argv[i + 1], 3600000, &value) && value) server.timeout_ms = value;
+ else if (!strcmp(argv[i], "--send-buffer") && number(argv[i + 1], INT32_MAX, &value)) server.send_buffer = (int)value;
+ else goto usage;
+ }
+ if (!server.path) goto usage;
+ if (pure_store_init(server.path) != PURE_OK) { fputs("Cannot initialize SQLite store\n", stderr); return 1; }
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, stop_server);
+ signal(SIGTERM, stop_server);
+ int listener = socket(AF_INET, SOCK_STREAM, 0);
+ if (listener < 0) { perror("socket"); return 1; }
+ int one = 1;
+ setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ struct sockaddr_in address = {.sin_family = AF_INET, .sin_port = htons((uint16_t)port),
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ if (bind(listener, (struct sockaddr *)&address, sizeof(address)) || listen(listener, SLOTS) || !nonblocking(listener)) {
+ perror("listen"); close(listener); return 1;
+ }
+ socklen_t address_size = sizeof(address);
+ if (getsockname(listener, (struct sockaddr *)&address, &address_size)) { close(listener); return 1; }
+ for (size_t i = 0; i < SLOTS; ++i) server.connections[i].fd = -1;
+ printf("{\"port\":%u,\"sqlite\":\"%s\"}\n", ntohs(address.sin_port), sqlite3_libversion());
+ fflush(stdout);
+ while (!stopping) {
+ struct pollfd polls[SLOTS + 1] = {{.fd = server.active < SLOTS ? listener : -1, .events = POLLIN}};
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ polls[i + 1] = (struct pollfd){.fd = c->fd, .events = c->phase == WRITING ? POLLOUT : POLLIN};
+ }
+ int ready = poll(polls, SLOTS + 1, 50);
+ if (ready < 0 && errno != EINTR) { perror("poll"); stopping = 1; }
+ uint64_t now = now_ms();
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ if (c->fd < 0) continue;
+ if (now >= c->deadline) { ++server.expired; close_connection(c); continue; }
+ short events = polls[i + 1].revents;
+ if (events & (POLLERR | POLLNVAL)) { close_connection(c); continue; }
+ if (events & (POLLIN | POLLOUT | POLLHUP)) {
+ if (c->phase == WRITING) write_connection(c); else read_connection(c);
+ }
+ }
+ if (!stopping && (polls[0].revents & POLLIN)) {
+ int fd = accept(listener, NULL, NULL);
+ if (fd < 0) continue;
+ if (!nonblocking(fd)) { close(fd); continue; }
+ if (server.send_buffer) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &server.send_buffer, sizeof(server.send_buffer));
+ for (size_t i = 0; i < SLOTS; ++i) if (server.connections[i].fd < 0) {
+ server.connections[i] = (Connection){.fd = fd, .server = &server, .deadline = now_ms() + server.timeout_ms};
+ ++server.active;
+ ++server.accepted;
+ if (server.active > server.peak_active) server.peak_active = server.active;
+ break;
+ }
+ }
+ }
+ close(listener);
+ for (size_t i = 0; i < SLOTS; ++i) close_connection(&server.connections[i]);
+ fprintf(stderr, "{\"active\":%zu,\"retained_payload_bytes\":%zu,\"peak_retained_payload_bytes\":%zu,"
+ "\"payload_budget\":%zu,\"peak_connections\":%zu,\"accepted\":%" PRIu64 ",\"commits\":%" PRIu64 ","
+ "\"gets\":%" PRIu64 ",\"conflicts\":%" PRIu64 ",\"budget_rejections\":%" PRIu64 ","
+ "\"expired\":%" PRIu64 ",\"releases\":%" PRIu64 ",\"ingress_prefix_copy_bytes\":%" PRIu64 ","
+ "\"borrowed_output_bytes\":%" PRIu64 ",\"server_structure_bytes\":%zu}\n",
+ server.active, server.retained, server.peak_retained, server.budget, server.peak_active,
+ server.accepted, server.commits, server.gets, server.conflicts, server.budget_rejections,
+ server.expired, server.releases, server.prefix_copy_bytes, server.borrowed_output_bytes, sizeof(server));
+ return 0;
+usage:
+ fputs("pure-connections --db PATH [--port 8767] [--budget BYTES] [--timeout-ms 10000] [--send-buffer BYTES]\n", stderr);
+ return 2;
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/store.c b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/store.c
new file mode 100644
index 0000000..a805f72
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/store.c
@@ -0,0 +1,132 @@
+#include "store.h"
+#include <limits.h>
+#include <string.h>
+
+static PureResult error_result(int rc) {
+ int code = rc & 255;
+ return code == SQLITE_BUSY || code == SQLITE_LOCKED ? PURE_BUSY : PURE_STORE_ERROR;
+}
+
+static int execute(sqlite3 *db, const char *sql) {
+ return sqlite3_exec(db, sql, NULL, NULL, NULL);
+}
+
+static int open_db(const char *path, sqlite3 **db, int flags) {
+ int rc = sqlite3_open_v2(path, db, flags | SQLITE_OPEN_NOMUTEX, NULL);
+ if (rc != SQLITE_OK) return rc;
+ sqlite3_busy_timeout(*db, 0); /* No hidden wait/retry on this owner thread. */
+ sqlite3_limit(*db, SQLITE_LIMIT_LENGTH, (int)PURE_OBJECT_LIMIT + 4096);
+ return execute(*db, "PRAGMA cache_size=-64; PRAGMA synchronous=FULL;");
+}
+
+PureResult pure_store_init(const char *path) {
+ sqlite3 *db = NULL;
+ int rc = open_db(path, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
+ sqlite3_stmt *mode = NULL;
+ if (rc == SQLITE_OK) rc = sqlite3_prepare_v2(db, "PRAGMA journal_mode=WAL", -1, &mode, NULL);
+ if (rc == SQLITE_OK) {
+ rc = sqlite3_step(mode);
+ if (rc == SQLITE_ROW) {
+ const unsigned char *name = sqlite3_column_text(mode, 0);
+ rc = name && strcmp((const char *)name, "wal") == 0 ? SQLITE_OK : SQLITE_ERROR;
+ }
+ }
+ sqlite3_finalize(mode);
+ if (rc == SQLITE_OK) rc = execute(db,
+ "CREATE TABLE IF NOT EXISTS pure_objects("
+ "key TEXT PRIMARY KEY, revision INTEGER NOT NULL CHECK(revision>0),"
+ "body BLOB NOT NULL CHECK(typeof(body)='blob'));");
+ if (db) sqlite3_close(db);
+ return rc == SQLITE_OK ? PURE_OK : error_result(rc);
+}
+
+void pure_store_release(PureStoredView *view) {
+ sqlite3_finalize(view->statement);
+ if (view->db) {
+ execute(view->db, "ROLLBACK");
+ sqlite3_close(view->db);
+ }
+ *view = (PureStoredView){0};
+}
+
+PureResult pure_store_get(const char *path, const char *key, size_t available,
+ PureStoredView *out) {
+ *out = (PureStoredView){0};
+ int rc = open_db(path, &out->db, SQLITE_OPEN_READONLY);
+ if (rc == SQLITE_OK) rc = execute(out->db, "BEGIN");
+ if (rc == SQLITE_OK) rc = sqlite3_prepare_v2(out->db,
+ "SELECT revision,length(body) FROM pure_objects WHERE key=?", -1, &out->statement, NULL);
+ if (rc == SQLITE_OK) rc = sqlite3_bind_text(out->statement, 1, key, -1, SQLITE_STATIC);
+ if (rc == SQLITE_OK) rc = sqlite3_step(out->statement);
+ PureResult result = PURE_STORE_ERROR;
+ if (rc == SQLITE_DONE) { result = PURE_NOT_FOUND; goto fail; }
+ if (rc != SQLITE_ROW) { result = error_result(rc); goto fail; }
+ out->revision = sqlite3_column_int64(out->statement, 0);
+ sqlite3_int64 size = sqlite3_column_int64(out->statement, 1);
+ if (out->revision <= 0 || size < 0) goto fail;
+ if (size > PURE_OBJECT_LIMIT) { result = PURE_LIMIT; goto fail; }
+ if ((uint64_t)size > available) { result = PURE_BUDGET; goto fail; }
+ sqlite3_finalize(out->statement);
+ out->statement = NULL;
+ /* Keep the read transaction so admission and body observe the same version.
+ * The result remains borrowed until socket completion/abort finalizes it. */
+ rc = sqlite3_prepare_v2(out->db, "SELECT body FROM pure_objects WHERE key=?", -1, &out->statement, NULL);
+ if (rc == SQLITE_OK) rc = sqlite3_bind_text(out->statement, 1, key, -1, SQLITE_STATIC);
+ if (rc == SQLITE_OK) rc = sqlite3_step(out->statement);
+ if (rc != SQLITE_ROW) { result = error_result(rc); goto fail; }
+ if (sqlite3_column_type(out->statement, 0) != SQLITE_BLOB) goto fail;
+ const unsigned char *data = sqlite3_column_blob(out->statement, 0);
+ int bytes = sqlite3_column_bytes(out->statement, 0);
+ if (bytes != size || (bytes && !data)) goto fail;
+ out->body = (PureSpan){data, (size_t)bytes};
+ return PURE_OK;
+fail:
+ pure_store_release(out);
+ return result;
+}
+
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ *revision = 0;
+ if (body.size > PURE_OBJECT_LIMIT || expected < 0) return PURE_LIMIT;
+ sqlite3 *db = NULL;
+ sqlite3_stmt *statement = NULL;
+ PureResult result = PURE_STORE_ERROR;
+ int rc = open_db(path, &db, SQLITE_OPEN_READWRITE);
+ if (rc == SQLITE_OK) rc = execute(db, "BEGIN IMMEDIATE");
+ if (rc != SQLITE_OK) { result = error_result(rc); goto finish; }
+ rc = sqlite3_prepare_v2(db, "SELECT revision FROM pure_objects WHERE key=?", -1, &statement, NULL);
+ if (rc == SQLITE_OK) rc = sqlite3_bind_text(statement, 1, key, -1, SQLITE_STATIC);
+ if (rc == SQLITE_OK) rc = sqlite3_step(statement);
+ if (rc == SQLITE_ROW) *revision = sqlite3_column_int64(statement, 0);
+ else if (rc != SQLITE_DONE) { result = error_result(rc); goto finish; }
+ sqlite3_finalize(statement);
+ statement = NULL;
+ if (*revision != expected) { result = PURE_CONFLICT; goto finish; }
+ if (*revision == INT64_MAX) { result = PURE_LIMIT; goto finish; }
+ const char *sql = *revision ?
+ "UPDATE pure_objects SET body=?1,revision=?2 WHERE key=?3" :
+ "INSERT INTO pure_objects(body,revision,key) VALUES(?1,?2,?3)";
+ rc = sqlite3_prepare_v2(db, sql, -1, &statement, NULL);
+ static const unsigned char empty = 0;
+ /* Do not copy at the binding boundary. Finalize before returning the input. */
+ if (rc == SQLITE_OK) rc = sqlite3_bind_blob(statement, 1, body.size ? body.data : &empty,
+ (int)body.size, SQLITE_STATIC);
+ if (rc == SQLITE_OK) rc = sqlite3_bind_int64(statement, 2, *revision + 1);
+ if (rc == SQLITE_OK) rc = sqlite3_bind_text(statement, 3, key, -1, SQLITE_STATIC);
+ if (rc == SQLITE_OK) rc = sqlite3_step(statement);
+ if (rc != SQLITE_DONE) { result = error_result(rc); goto finish; }
+ rc = sqlite3_finalize(statement);
+ statement = NULL;
+ if (rc == SQLITE_OK) rc = execute(db, "COMMIT");
+ if (rc != SQLITE_OK) { result = error_result(rc); goto finish; }
+ ++*revision;
+ result = PURE_OK; /* Acknowledgment is constructed only after COMMIT. */
+finish:
+ sqlite3_finalize(statement);
+ if (db) {
+ if (!sqlite3_get_autocommit(db)) execute(db, "ROLLBACK");
+ sqlite3_close(db);
+ }
+ return result;
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/store.h b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/store.h
new file mode 100644
index 0000000..c0e9f96
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/store.h
@@ -0,0 +1,25 @@
+#ifndef PURE_STORE_H
+#define PURE_STORE_H
+#include "flow.h"
+#include <sqlite3.h>
+#include <stdint.h>
+
+#define PURE_OBJECT_LIMIT ((2u * 6u + 32u) * 32768u + 8192u)
+typedef enum {
+ PURE_OK, PURE_NOT_FOUND, PURE_CONFLICT, PURE_BUSY, PURE_BUDGET,
+ PURE_LIMIT, PURE_STORE_ERROR
+} PureResult;
+typedef struct {
+ sqlite3 *db;
+ sqlite3_stmt *statement;
+ PureSpan body;
+ int64_t revision;
+} PureStoredView;
+
+PureResult pure_store_init(const char *path);
+PureResult pure_store_get(const char *path, const char *key, size_t available,
+ PureStoredView *out);
+void pure_store_release(PureStoredView *);
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/test-flow.c b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/test-flow.c
new file mode 100644
index 0000000..997e7df
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/connections/test-flow.c
@@ -0,0 +1,110 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+typedef struct { unsigned char *bytes; unsigned releases; } Owner;
+static void release(void *raw) {
+ Owner *owner = raw;
+ free(owner->bytes);
+ owner->bytes = NULL;
+ ++owner->releases;
+}
+
+static void transfers(void) {
+ Owner owner = {.bytes = malloc(5)};
+ CHECK(owner.bytes);
+ memcpy(owner.bytes, "a\0bcd", 5);
+ PureTransfer transfer = {0};
+ pure_transfer_init(&transfer, (PureSpan){(const unsigned char *)"head", 4},
+ (PureSpan){owner.bytes, 5}, &owner, release);
+ CHECK(!pure_transfer_consume(&transfer, 5));
+ CHECK(transfer.active && !owner.releases);
+ CHECK(pure_transfer_consume(&transfer, 0));
+ unsigned char received[9];
+ size_t used = 0;
+ while (transfer.active) {
+ PureSpan span = pure_transfer_next(&transfer, 2);
+ CHECK(span.size && span.size <= 2);
+ memcpy(received + used, span.data, span.size);
+ used += span.size;
+ CHECK(pure_transfer_consume(&transfer, span.size));
+ CHECK((used == 9) == (owner.releases == 1));
+ }
+ CHECK(used == 9 && !memcmp(received, "heada\0bcd", 9));
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 1 && !pure_transfer_consume(&transfer, 0));
+ owner.bytes = malloc(3);
+ CHECK(owner.bytes);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){owner.bytes, 3}, &owner, release);
+ CHECK(pure_transfer_consume(&transfer, 1));
+ pure_transfer_abort(&transfer);
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 2 && !transfer.active);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){0}, &owner, release);
+ CHECK(owner.releases == 3 && !transfer.active);
+}
+
+static void storage(const char *path) {
+ CHECK(pure_store_init(path) == PURE_OK);
+ PureStoredView first, second;
+ CHECK(pure_store_get(path, "missing", 100, &first) == PURE_NOT_FOUND);
+ CHECK(!first.db && !first.statement);
+ static const unsigned char original[] = {0, 1, 2, 255, 17};
+ static const unsigned char updated[] = {9, 8, 7};
+ int64_t revision;
+ CHECK(pure_store_put(path, "work", 0, (PureSpan){original, sizeof(original)}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ CHECK(pure_store_get(path, "work", sizeof(original) - 1, &first) == PURE_BUDGET);
+ CHECK(!first.db && !first.statement);
+ CHECK(pure_store_get(path, "work", sizeof(original), &first) == PURE_OK);
+ CHECK(first.body.size == sizeof(original) && first.revision == 1);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 2);
+ CHECK(!memcmp(first.body.data, original, sizeof(original)));
+ CHECK(pure_store_get(path, "work", 100, &second) == PURE_OK);
+ CHECK(second.revision == 2 && second.body.size == sizeof(updated));
+ CHECK(!memcmp(second.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ pure_store_release(&first);
+ pure_store_release(&second);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){original, sizeof(original)}, &revision) == PURE_CONFLICT);
+ CHECK(revision == 2);
+
+ sqlite3 *other = NULL;
+ CHECK(sqlite3_open(path, &other) == SQLITE_OK);
+ CHECK(sqlite3_exec(other, "BEGIN IMMEDIATE", NULL, NULL, NULL) == SQLITE_OK);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_BUSY);
+ CHECK(sqlite3_exec(other, "ROLLBACK", NULL, NULL, NULL) == SQLITE_OK);
+ CHECK(sqlite3_exec(other, "CREATE TRIGGER deny BEFORE UPDATE ON pure_objects "
+ "BEGIN SELECT RAISE(ABORT,'injected failure'); END", NULL, NULL, NULL) == SQLITE_OK);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 2 && !memcmp(first.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ CHECK(sqlite3_exec(other, "DROP TRIGGER deny; UPDATE pure_objects SET revision=9223372036854775807", NULL, NULL, NULL) == SQLITE_OK);
+ CHECK(pure_store_put(path, "work", INT64_MAX, (PureSpan){original, sizeof(original)}, &revision) == PURE_LIMIT);
+ CHECK(sqlite3_close(other) == SQLITE_OK);
+ CHECK(pure_store_put(path, "empty", 0, (PureSpan){0}, &revision) == PURE_OK);
+ CHECK(pure_store_get(path, "empty", 0, &first) == PURE_OK && first.body.size == 0);
+ pure_store_release(&first);
+}
+
+int main(void) {
+ transfers();
+ char directory[] = "/tmp/pure-connection-unit-XXXXXX";
+ CHECK(mkdtemp(directory));
+ char path[256], sidecar[280];
+ snprintf(path, sizeof(path), "%s/store.db", directory);
+ storage(path);
+ CHECK(unlink(path) == 0);
+ snprintf(sidecar, sizeof(sidecar), "%s-wal", path); unlink(sidecar);
+ snprintf(sidecar, sizeof(sidecar), "%s-shm", path); unlink(sidecar);
+ CHECK(rmdir(directory) == 0);
+ puts("{\"transfer\":\"partial-consumption-and-single-release\","
+ "\"storage\":\"snapshot-budget-conflict-busy-rollback-overflow-empty\"}");
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/cli.mjs b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/cli.mjs
new file mode 100644
index 0000000..b67f4d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/cli.mjs
@@ -0,0 +1,127 @@
+#!/usr/bin/env node
+import { readFile, writeFile } from 'node:fs/promises';
+import { createInterface } from 'node:readline';
+import { createRuntime } from './web/runtime.mjs';
+import { parseProject } from './web/project.mjs';
+import { remoteTarget, pushProject, pullProject } from './remote.mjs';
+
+const help = `Pure authoring workbench · 같은 정의와 Zig 실행기
+ load PATH .pure 파일을 적용 (같은 이름의 상태 보존)
+ down NAME 정의한 입력 누르기
+ up NAME 정의한 입력 놓기
+ point NAME PHASE X Y 좌표 입력 (down / move / up / cancel)
+ point-target NAME VIEW PHASE X Y 그룹의 대상에 좌표 입력
+ change NAME VALUE 숫자 입력 전달
+ frame [1..600] 시간 진행, 1프레임 = 1/60초
+ show 상태와 도형 출력
+ limits C H W 표시 캐시(0..32)·변경 기록(0..8)·작업량(0..4294967295) 설정
+ forget [PART] 표시 기록 삭제: all, values, history (상태는 유지)
+ costs 마지막 표시 계산의 작업량·명령 수·캐시 적중 출력
+ reset 현재 정의의 초기 상태로
+ save PATH 적용한 정의를 저장
+ save-project PATH 적용 코드와 현재 배치를 JSON으로 저장
+ restore PATH 저장한 배치를 복원 (초안이 있으면 파일에 보존)
+ connect URL KEY 로컬 네이티브 저장 서버의 작업물에 연결
+ push [REVISION] 현재 배치를 저장 (첫 생성은 push 0, 충돌 시 기존 값 유지)
+ pull 원격 배치를 검증·복원하고 revision 기억
+ help / quit
+브라우저와 별도 인스턴스입니다. 임의 JavaScript는 실행하지 않습니다.`;
+
+async function main() {
+ const args = process.argv.slice(2);
+ if (args.includes('--help')) { console.log(help); return; }
+ if (args.length > 1) throw new Error('사용법: node cli.mjs [project.pure]');
+ const runtime = await createRuntime(await readFile(new URL('./web/core.wasm', import.meta.url)));
+ let savedDraft = null;
+ let remote = null, remoteRevision = null;
+ async function loadFile(path, restoreOnly = false) {
+ const content = await readFile(path, 'utf8');
+ if (restoreOnly || path.toLowerCase().endsWith('.json')) {
+ const project = parseProject(content);
+ if (project.version === 2) {
+ savedDraft = runtime.restoreDocument(project).draft;
+ return;
+ }
+ if (restoreOnly) throw new Error('현재 배치가 포함된 version 2 파일이 필요합니다.');
+ runtime.apply(project.source);
+ } else runtime.apply(content);
+ savedDraft = null;
+ }
+ if (args[0]) await loadFile(args[0]); else runtime.apply('');
+ const terminal = createInterface({ input: process.stdin, output: process.stdout, terminal: Boolean(process.stdin.isTTY) });
+ if (process.stdin.isTTY) console.log(help);
+ terminal.setPrompt('pure> ');
+ if (process.stdin.isTTY) terminal.prompt();
+ for await (const line of terminal) {
+ try {
+ const match = /^(\S+)(?:\s+(.+))?$/.exec(line.trim());
+ const name = match?.[1] || 'show';
+ const arg = match?.[2];
+ if (name === 'quit') { terminal.close(); break; }
+ if (name === 'help') console.log(help);
+ else if (name === 'costs' && !arg) console.log(JSON.stringify({ evaluation: runtime.evaluationStats() }));
+ else {
+ if (name === 'load' && arg) await loadFile(arg);
+ else if (name === 'restore' && arg) await loadFile(arg, true);
+ else if (name === 'connect' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('connect URL KEY 형식을 사용하세요.');
+ remote = remoteTarget(parts[0], parts[1]);
+ remoteRevision = null;
+ console.log(JSON.stringify({ remote: remote.href }));
+ } else if (name === 'push') {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const expected = arg ?? remoteRevision;
+ if (expected === null) throw new Error('먼저 pull로 버전을 읽거나 push 0으로 새 작업물을 만드세요.');
+ remoteRevision = await pushProject(remote, expected, runtime.exportDocument(savedDraft ?? undefined));
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, stored: true }));
+ } else if (name === 'pull' && !arg) {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const loaded = await pullProject(remote);
+ savedDraft = runtime.restoreDocument(loaded.project).draft;
+ remoteRevision = loaded.revision;
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, restored: true }));
+ }
+ else if (name === 'save-project' && arg) await writeFile(arg, JSON.stringify(runtime.exportDocument(savedDraft ?? undefined), null, 2) + '\n', {flag:'wx'});
+ else if (name === 'save' && arg) await writeFile(arg, runtime.exportProject().source, { flag: 'wx' });
+ else if (name === 'down' && arg) runtime.down(arg, 'terminal');
+ else if (name === 'up' && arg) runtime.up(arg, 'terminal');
+ else if (name === 'point' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 4) throw new Error('point NAME PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[1], Number(parts[2]), Number(parts[3]), 'terminal');
+ } else if (name === 'point-target' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 5) throw new Error('point-target NAME VIEW PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[2], Number(parts[3]), Number(parts[4]), 'terminal', parts[1]);
+ } else if (name === 'change' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('change NAME VALUE 형식을 사용하세요.');
+ runtime.change(parts[0], Number(parts[1]), 'terminal');
+ } else if (name === 'frame') {
+ if (arg !== undefined && !/^\d+$/.test(arg)) throw new Error('frame 1..600 정수를 입력하세요.');
+ const count = arg === undefined ? 1 : Number(arg);
+ if (count < 1 || count > 600) throw new Error('frame 1..600 정수를 입력하세요.');
+ runtime.frame(count);
+ } else if (name === 'reset' && !arg) runtime.reset();
+ else if (name === 'limits' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 3 || parts.some(part => !/^\d+$/.test(part)))
+ throw new Error('limits C H W 정수 세 개를 입력하세요.');
+ const [cacheEntries, historyEntries, workLimit] = parts.map(Number);
+ runtime.configureEvaluation({ cacheEntries, historyEntries, workLimit });
+ } else if (name === 'forget') runtime.forgetEvaluation(arg || 'all');
+ else if (name !== 'show' || arg) throw new Error('명령 형식을 확인하세요. help로 안내를 볼 수 있습니다.');
+ const result = runtime.snapshot();
+ console.log(JSON.stringify(result));
+ if (result.lastError && !process.stdin.isTTY) process.exitCode = 1;
+ }
+ } catch (error) {
+ console.error(`${error.line ? `${error.line}:${error.column || 1} ` : ''}${error.message}`);
+ if (!process.stdin.isTTY) process.exitCode = 1;
+ }
+ if (process.stdin.isTTY) terminal.prompt();
+ }
+}
+
+main().catch((error) => { console.error(error.message); process.exitCode = 1; });
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/cli.test.mjs b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/cli.test.mjs
new file mode 100644
index 0000000..f355d2d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/cli.test.mjs
@@ -0,0 +1,121 @@
+import test from 'node:test';
+import assert from 'node:assert/strict';
+import { spawnSync } from 'node:child_process';
+import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
+import { tmpdir } from 'node:os';
+import { join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { createRuntime } from './web/runtime.mjs';
+
+const root = fileURLToPath(new URL('.', import.meta.url));
+function run(input, file) {
+ const result = spawnSync(process.execPath, [join(root, 'cli.mjs'), ...(file ? [file] : [])], {
+ input, encoding: 'utf8', cwd: root,
+ });
+ if (result.error) throw result.error;
+ return { ...result, snapshots: result.stdout.split('\n').filter(line => line.startsWith('{')).map(line => JSON.parse(line)) };
+}
+
+test('terminal starts empty and produces the same charge trace as the shared runtime', async () => {
+ assert.deepEqual(run('show\nquit\n').snapshots[0].states, {});
+ const file = join(root, 'examples/charge.pure');
+ const result = run('down jump\nframe 30\nup jump\nframe 1\nshow\nquit\n', file);
+ assert.equal(result.status, 0, result.stderr);
+ const runtime = await createRuntime(await readFile(join(root, 'web/core.wasm')));
+ runtime.apply(await readFile(file, 'utf8'));
+ runtime.down('jump', 'terminal'); runtime.frame(30); runtime.up('jump', 'terminal'); runtime.frame();
+ // JSON has no undefined-valued optional fields; compare the same wire form.
+ assert.deepEqual(result.snapshots.at(-1), JSON.parse(JSON.stringify(runtime.snapshot())));
+ assert(result.snapshots.at(-1).states.y < 240);
+});
+
+test('invalid terminal commands do not alter state and fail piped execution', () => {
+ const result = run('show\nframe 0\nframe -1\nframe 1.5\nframe 1e2\nframe 601\nshow extra\ndown unknown\nshow\nquit\n', join(root, 'examples/counter.pure'));
+ assert.equal(result.status, 1);
+ assert.deepEqual(result.snapshots[0], result.snapshots[1]);
+ assert.equal(result.stderr.trim().split('\n').length, 7);
+});
+
+test('terminal replays authored pointer movement and cancellation through the shared runtime', async () => {
+ const file = join(root, 'examples/direct.pure');
+ const result = run('point drag down 90 170\npoint drag move 360 220\npoint drag up 410 240\npoint drag down 410 240\npoint drag move 500 260\npoint drag cancel 500 260\nshow\nquit\n', file);
+ assert.equal(result.status, 0, result.stderr);
+ const runtime = await createRuntime(await readFile(join(root, 'web/core.wasm')));
+ runtime.apply(await readFile(file, 'utf8'));
+ for (const [phase, x, y] of [['down',90,170],['move',360,220],['up',410,240],['down',410,240],['move',500,260],['cancel',500,260]])
+ runtime.point('drag', phase, x, y, 'terminal');
+ assert.deepEqual(result.snapshots.at(-1), JSON.parse(JSON.stringify(runtime.snapshot())));
+ assert.equal(result.snapshots.at(-1).states.x, 350);
+ assert.equal(result.snapshots.at(-1).states.y, 210);
+ assert.deepEqual(result.snapshots.at(-1).held, []);
+});
+
+test('file load preserves by name, rejected load preserves active work, and save never overwrites', async t => {
+ const directory = await mkdtemp(join(tmpdir(), 'pure-author-cli-'));
+ t.after(() => rm(directory, { recursive: true, force: true }));
+ const first = join(directory, 'first.pure'), second = join(directory, 'second with space.pure');
+ const invalid = join(directory, 'invalid.pure'), saved = join(directory, 'saved.pure');
+ await writeFile(first, 'state n = 7');
+ await writeFile(second, 'state n = 100\nstate added = 9');
+ await writeFile(invalid, 'state n = broken');
+ const result = run(`load ${second}\nload ${invalid}\nshow\nsave ${saved}\nreset\nsave ${saved}\nquit\n`, first);
+ assert.equal(result.status, 1);
+ assert.deepEqual(result.snapshots[0].states, { n: 7, added: 9 });
+ assert.deepEqual(result.snapshots[1], result.snapshots[0]);
+ assert.deepEqual(result.snapshots.at(-1).states, { n: 100, added: 9 });
+ assert.equal(await readFile(saved, 'utf8'), await readFile(second, 'utf8'));
+ assert.match(result.stderr, /EEXIST/);
+});
+
+test('terminal exposes arithmetic rollback and retains failure through matching release', async t => {
+ const directory = await mkdtemp(join(tmpdir(), 'pure-author-error-'));
+ t.after(() => rm(directory, { recursive: true, force: true }));
+ const file = join(directory, 'error.pure');
+ await writeFile(file, 'state n = 7\ninput tap = Space\non tap.down { n = 1 / 0 }');
+ const result = run('down tap\nup tap\nshow\nreset\nquit\n', file);
+ assert.equal(result.status, 1);
+ for (const snapshot of result.snapshots.slice(0, 3)) {
+ assert.equal(snapshot.states.n, 7); assert.equal(snapshot.lastError, 4);
+ assert.equal(snapshot.errorLine, 3);
+ }
+ assert.equal(result.snapshots[3].lastError, 0);
+});
+
+test('terminal configures and discards evaluation records and recovers from a display limit', () => {
+ const result = run('limits 32 8 2048\nshow\ncosts\nforget all\nlimits 32 8 0\nlimits 32 8 2048\nshow\nquit\n', join(root, 'examples/counter.pure'));
+ assert.equal(result.status, 1); // The explicit zero-budget display failed.
+ assert.equal(result.stderr, '');
+ const [configured, warm, costs, forgotten, limited, recovered, final] = result.snapshots;
+ assert.deepEqual(warm.views, configured.views);
+ assert(costs.evaluation.cacheHits > 0);
+ assert.deepEqual(forgotten.states, configured.states);
+ assert.deepEqual(limited.views, []);
+ assert.equal(limited.lastError, 101);
+ assert.deepEqual(recovered, final);
+ assert.deepEqual(recovered.views, configured.views);
+ assert.deepEqual(recovered.states, configured.states);
+});
+
+test('terminal saves and restores placement independently of reset and preserves a browser draft', async t => {
+ const directory = await mkdtemp(join(tmpdir(), 'pure-layout-cli-'));
+ t.after(() => rm(directory, {recursive:true,force:true}));
+ const saved=join(directory,'layout.json'), copied=join(directory,'copy.json');
+ const first=run(`point drag down 90 170\npoint drag move 360 220\npoint drag up 90 170\nsave-project ${saved}\nreset\nrestore ${saved}\nshow\nquit\n`,join(root,'examples/direct.pure'));
+ assert.equal(first.status,0,first.stderr);assert.equal(first.snapshots.at(-1).states.x,350);
+ const document=JSON.parse(await readFile(saved,'utf8'));document.draft='state incomplete =';
+ await writeFile(saved,JSON.stringify(document));
+ const second=run(`save-project ${copied}\nreset\nshow\nquit\n`,saved);
+ assert.equal(second.status,0,second.stderr);assert.equal(second.snapshots.at(-1).states.x,80);
+ const copy=JSON.parse(await readFile(copied,'utf8'));assert.equal(copy.draft,document.draft);assert.deepEqual(copy.states,document.states);
+ const rejected=run(`save-project ${saved}\nquit\n`,saved);
+ assert.equal(rejected.status,1);assert.match(rejected.stderr,/EEXIST/);
+});
+
+test('invalid restoration leaves terminal code and state unchanged', async t => {
+ const directory=await mkdtemp(join(tmpdir(),'pure-invalid-layout-'));
+ t.after(()=>rm(directory,{recursive:true,force:true}));
+ const file=join(directory,'bad.json');
+ await writeFile(file,JSON.stringify({format:'pure-workbench',version:2,source:'state x=1',states:[]}));
+ const result=run(`show\nrestore ${file}\nshow\nquit\n`,join(root,'examples/counter.pure'));
+ assert.equal(result.status,1);assert.deepEqual(result.snapshots[0],result.snapshots[1]);
+});
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/examples/direct.pure b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/examples/direct.pure
new file mode 100644
index 0000000..b29721c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/examples/direct.pure
@@ -0,0 +1,47 @@
+# 도형을 잡은 위치를 유지해 이동합니다. 취소하면 잡기 전 위치로 돌아갑니다.
+state x = 80
+state y = 160
+state grab_x = 0
+state grab_y = 0
+state start_x = 80
+state start_y = 160
+state dragging = 0
+
+input drag = pointer(tile)
+input left = ArrowLeft
+input right = ArrowRight
+
+box left_area(20, 100, 280, 220, "#233a31")
+box right_area(340, 100, 280, 220, "#343b25")
+box tile(x, y, 56, 44, "#c9f08b")
+text horizontal(30, 45, x, "x: ")
+text vertical(180, 45, y, "y: ")
+text region(350, 70, x >= 320, "오른쪽 영역: ")
+text active(30, 75, dragging, "잡고 있음: ")
+
+on drag.down {
+ start_x = x
+ start_y = y
+ grab_x = event_x - x
+ grab_y = event_y - y
+ dragging = 1
+}
+on drag.move {
+ x = clamp(event_x - grab_x, 20, 564)
+ y = clamp(event_y - grab_y, 100, 276)
+}
+on drag.up {
+ # 놓기는 마지막으로 표시한 위치를 확정합니다.
+ dragging = 0
+}
+on drag.cancel {
+ x = start_x
+ y = start_y
+ dragging = 0
+}
+on left.down {
+ if dragging == 0 { x = max(20, x - 10) }
+}
+on right.down {
+ if dragging == 0 { x = min(564, x + 10) }
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/remote.mjs b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/remote.mjs
new file mode 100644
index 0000000..6ee6a59
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/remote.mjs
@@ -0,0 +1,89 @@
+import http from 'node:http';
+import { MAX_PROJECT_BYTES, parseProject } from './web/project.mjs';
+
+const maxRevision = 9223372036854775807n;
+function revisionText(value, allowZero = false) {
+ if (typeof value !== 'string' || !/^(0|[1-9]\d*)$/.test(value) ||
+ value.length > 19 || BigInt(value) > maxRevision || (!allowZero && value === '0'))
+ throw new Error('revision은 범위 안의 정수 문자열이어야 합니다.');
+ return value;
+}
+
+export function remoteTarget(base, key) {
+ const url = new URL(base);
+ if (url.protocol !== 'http:' || !['127.0.0.1', 'localhost'].includes(url.hostname) ||
+ url.username || url.password || url.pathname !== '/' || url.search || url.hash)
+ throw new Error('현재 연결 호스트는 로컬 http://127.0.0.1:PORT 형식을 사용합니다.');
+ if (!/^[A-Za-z0-9_-]{1,64}$/.test(key)) throw new Error('작업물 이름은 영문·숫자·_·- 1~64자입니다.');
+ url.hostname = '127.0.0.1';
+ url.pathname = `/objects/${key}`;
+ return url;
+}
+
+function request(url, method, body, headers = {}) {
+ return new Promise((resolve, reject) => {
+ let done = false;
+ const finish = (error, value) => {
+ if (done) return;
+ done = true;
+ clearTimeout(deadline);
+ if (error) reject(error); else resolve(value);
+ };
+ const req = http.request(url, { method, agent: false, headers: { ...headers,
+ 'Content-Length': body?.byteLength ?? 0, Connection: 'close' } }, (res) => {
+ const chunks = [];
+ let size = 0;
+ res.on('data', (chunk) => {
+ size += chunk.length;
+ if (size > MAX_PROJECT_BYTES) {
+ const error = new Error('서버 작업물이 허용 크기를 넘었습니다.');
+ finish(error);
+ res.destroy(error);
+ req.destroy(error);
+ } else chunks.push(chunk);
+ });
+ res.on('error', (error) => finish(error));
+ res.on('aborted', () => finish(new Error('응답이 완료되기 전에 연결이 끊겼습니다.')));
+ res.on('end', () => {
+ if (res.statusCode !== 200) {
+ const error = new Error(`원격 작업 실패: ${res.statusCode} ${res.headers['x-pure-error'] ?? ''}`.trim());
+ error.status = res.statusCode;
+ error.etag = res.headers.etag;
+ finish(error);
+ return;
+ }
+ try {
+ const match = /^"([1-9]\d*)"$/.exec(res.headers.etag ?? '');
+ if (!match) throw new Error('서버의 revision 응답이 올바르지 않습니다.');
+ const revision = revisionText(match[1]);
+ finish(null, { revision, bytes: Buffer.concat(chunks, size) });
+ } catch (error) { finish(error); }
+ });
+ });
+ const deadline = setTimeout(() => {
+ const error = new Error('원격 작업 시간 초과: 저장 완료 여부는 다시 확인해야 합니다.');
+ finish(error);
+ req.destroy(error);
+ }, 12000);
+ req.on('error', (error) => finish(error));
+ req.end(body);
+ });
+}
+
+export async function pushProject(target, expected, project) {
+ revisionText(expected, true);
+ const text = JSON.stringify(project);
+ parseProject(text);
+ const body = Buffer.from(text, 'utf8');
+ const headers = expected === '0' ? { 'If-None-Match': '*' } : { 'If-Match': `"${expected}"` };
+ const result = await request(target, 'PUT', body, headers);
+ return result.revision;
+}
+
+export async function pullProject(target) {
+ const result = await request(target, 'GET');
+ const text = new TextDecoder('utf-8', { fatal: true }).decode(result.bytes);
+ const project = parseProject(text);
+ if (project.version !== 2) throw new Error('현재 배치를 포함한 version 2 작업물이 필요합니다.');
+ return { project, revision: result.revision };
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/compiler.mjs b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/compiler.mjs
new file mode 100644
index 0000000..6aec335
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/compiler.mjs
@@ -0,0 +1,496 @@
+// Pure's experimental scalar interaction language. No host code is evaluated.
+const LIMITS = Object.freeze({ sourceBytes: 32768, states: 32, inputs: 8,
+ views: 24, handlers: 64, instructions: 512, depth: 64, stack: 64 });
+const RESERVED = new Set(['frame', 'dt', 'event_x', 'event_y', 'event_value', 'min', 'max', 'clamp']);
+const BINARY = new Map([
+ ['||', [1, 15]], ['&&', [2, 14]], ['==', [3, 12]], ['!=', [3, 13]],
+ ['<', [4, 8]], ['<=', [4, 9]], ['>', [4, 10]], ['>=', [4, 11]],
+ ['+', [5, 3]], ['-', [5, 4]], ['*', [6, 5]], ['/', [6, 6]],
+]);
+const FUNCTIONS = { min: [2, 17], max: [2, 18], clamp: [3, 19] };
+const VIEW_FIELDS = { box: ['x', 'y', 'width', 'height'],
+ circle: ['x', 'y', 'radius'], text: ['x', 'y', 'value'] };
+
+function fail(token, message) {
+ const error = new Error(`${message} (${token.line}:${token.column})`);
+ error.line = token.line;
+ error.column = token.column;
+ throw error;
+}
+
+function lex(source) {
+ const tokens = [];
+ let offset = 0, line = 1, column = 1;
+ const advance = () => {
+ const char = source[offset++];
+ if (char === '\n') { line++; column = 1; } else column++;
+ return char;
+ };
+ while (offset < source.length) {
+ const char = source[offset];
+ if (char === ' ' || char === '\t' || char === '\r') { advance(); continue; }
+ if (char === '#') { while (offset < source.length && source[offset] !== '\n') advance(); continue; }
+ const token = { line, column };
+ if (char === '\n') { advance(); tokens.push({ ...token, kind: 'nl' }); continue; }
+ if (char === '"') {
+ advance();
+ let value = '', closed = false;
+ while (offset < source.length) {
+ const next = advance();
+ if (next === '"') { closed = true; break; }
+ if (next === '\n' || next === '\r') fail(token, 'Strings must fit on one line');
+ if (next === '\\') {
+ const escaped = advance();
+ const escapes = { n: '\n', r: '\r', t: '\t', '"': '"', '\\': '\\' };
+ if (!Object.hasOwn(escapes, escaped)) fail(token, 'Unsupported string escape');
+ value += escapes[escaped];
+ } else value += next;
+ }
+ if (!closed) fail(token, 'Unterminated string');
+ tokens.push({ ...token, kind: 'string', value }); continue;
+ }
+ const remaining = source.slice(offset);
+ const number = remaining.match(/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/);
+ if (number) {
+ const value = Number(number[0]);
+ if (!Number.isFinite(value)) fail(token, 'Number must be finite');
+ for (let i = 0; i < number[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'number', value }); continue;
+ }
+ const name = remaining.match(/^[A-Za-z_][A-Za-z_0-9]*/);
+ if (name) {
+ for (let i = 0; i < name[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'name', value: name[0] }); continue;
+ }
+ const pair = source.slice(offset, offset + 2);
+ if (['<=', '>=', '==', '!=', '&&', '||'].includes(pair)) {
+ advance(); advance(); tokens.push({ ...token, kind: pair }); continue;
+ }
+ if ('=+-*/!<>(){},.;:'.includes(char)) {
+ advance(); tokens.push({ ...token, kind: char }); continue;
+ }
+ fail(token, `Unexpected character ${JSON.stringify(char)}`);
+ }
+ tokens.push({ kind: 'eof', line, column });
+ return tokens;
+}
+
+class Parser {
+ constructor(tokens) { this.tokens = tokens; this.position = 0; this.depth = 0; }
+ peek() { return this.tokens[this.position]; }
+ take() { return this.tokens[this.position++]; }
+ is(kind, value) { return this.peek().kind === kind && (value === undefined || this.peek().value === value); }
+ expect(kind, description = kind) {
+ if (!this.is(kind)) fail(this.peek(), `Expected ${description}`);
+ return this.take();
+ }
+ newlines() { while (this.is('nl')) this.take(); }
+ separators() { while (this.is('nl') || this.is(';')) this.take(); }
+ end() {
+ if (!['nl', ';', '}', 'eof'].includes(this.peek().kind)) fail(this.peek(), 'Expected newline or semicolon');
+ this.separators();
+ }
+ reference(token) {
+ if (!this.is('.')) return token.value;
+ this.take();
+ return `${token.value}.${this.expect('name', 'field name').value}`;
+ }
+ initial() {
+ let sign = 1;
+ if (this.is('-') || this.is('+')) sign = this.take().kind === '-' ? -1 : 1;
+ return sign * this.expect('number', 'numeric state initializer').value;
+ }
+ node(token, properties, children = []) {
+ const depth = 1 + Math.max(0, ...children.map(child => child.depth));
+ if (depth > LIMITS.depth) fail(token, 'Expression nesting exceeds 64');
+ return { token, depth, ...properties };
+ }
+ expression(minimum = 0, multiline = false) {
+ if (++this.depth > LIMITS.depth) fail(this.peek(), 'Expression nesting exceeds 64');
+ if (multiline) this.newlines();
+ const token = this.take();
+ let left;
+ if (token.kind === 'number') left = this.node(token, { kind: 'constant', value: token.value });
+ else if (token.kind === '-' || token.kind === '!') {
+ const child = this.expression(7, multiline);
+ left = this.node(token, { kind: 'unary', op: token.kind === '-' ? 7 : 16, child }, [child]);
+ } else if (token.kind === '(') {
+ left = this.expression(0, true); this.newlines(); this.expect(')');
+ } else if (token.kind === 'name') {
+ if (Object.hasOwn(FUNCTIONS, token.value) && this.is('(')) {
+ this.take();
+ const args = [];
+ this.newlines();
+ if (!this.is(')')) {
+ for (;;) {
+ args.push(this.expression(0, true)); this.newlines();
+ if (!this.is(',')) break;
+ this.take();
+ }
+ }
+ this.expect(')');
+ if (args.length !== FUNCTIONS[token.value][0]) fail(token, `${token.value} expects ${FUNCTIONS[token.value][0]} arguments`);
+ left = this.node(token, { kind: 'call', op: FUNCTIONS[token.value][1], args }, args);
+ } else left = this.node(token, { kind: 'reference', name: this.reference(token) });
+ } else fail(token, 'Expected a number, state, or expression');
+ for (;;) {
+ if (multiline) this.newlines();
+ const entry = BINARY.get(this.peek().kind);
+ if (!entry || entry[0] < minimum) break;
+ const operator = this.take();
+ const right = this.expression(entry[0] + 1, multiline);
+ left = this.node(operator, { kind: 'binary', op: entry[1], left, right }, [left, right]);
+ }
+ this.depth--;
+ return left;
+ }
+ block(depth = 0) {
+ if (depth >= LIMITS.depth) fail(this.peek(), 'Handler nesting exceeds 64');
+ this.newlines(); this.expect('{'); this.separators();
+ const statements = [];
+ while (!this.is('}')) {
+ const token = this.expect('name', 'assignment, if, or closing brace');
+ if (token.value === 'if' && !this.is('=')) {
+ const condition = this.expression();
+ const body = this.block(depth + 1);
+ statements.push({ kind: 'if', token, condition, body });
+ } else {
+ const name = this.reference(token);
+ this.expect('=');
+ statements.push({ kind: 'assign', token, name, expression: this.expression() });
+ }
+ this.end();
+ }
+ this.take();
+ return statements;
+ }
+ parse() {
+ const declarations = [];
+ this.separators();
+ while (!this.is('eof')) {
+ const token = this.expect('name', 'declaration');
+ const kind = token.value;
+ if (kind === 'state') {
+ const name = this.expect('name', 'state name'); this.expect('=');
+ declarations.push({ kind, token, name, initial: this.initial() });
+ } else if (kind === 'record') {
+ const name = this.expect('name', 'record type'); this.newlines(); this.expect('{'); this.separators();
+ const fields = [];
+ while (!this.is('}')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,fields});
+ } else if (kind === 'item') {
+ const name = this.expect('name', 'item name'); this.expect('=');
+ const type = this.expect('name', 'record type'); this.expect('('); this.newlines();
+ const fields = [];
+ while (!this.is(')')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.newlines();
+ if (!this.is(',')) break;
+ this.take(); this.newlines();
+ }
+ this.expect(')'); declarations.push({kind,token,name,type,fields});
+ } else if (kind === 'rule') {
+ const name = this.expect('name', 'rule name'); this.expect('(');
+ const parameter = this.expect('name', 'record parameter'); this.expect(':');
+ const type = this.expect('name', 'record type'); this.expect(')');
+ declarations.push({kind,token,name,parameter,type,body:this.block()});
+ } else if (kind === 'input') {
+ const name = this.expect('name', 'input name'); this.expect('=');
+ const key = this.expect('name', 'keyboard code or pointer(view)');
+ if (key.value === 'value') {
+ declarations.push({kind,token,name,valueInput:true}); this.end(); continue;
+ }
+ if (key.value === 'pointer') {
+ if (this.is('{')) {
+ this.take(); this.separators(); const routes = [];
+ while (!this.is('}')) {
+ const target = this.expect('name', 'view ID'); this.expect(':');
+ const item = this.expect('name', 'item name'); routes.push({target,item}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,routes}); this.end(); continue;
+ }
+ this.expect('(');
+ const target = this.expect('name', 'view ID'); this.expect(')');
+ declarations.push({ kind, token, name, target });
+ this.end(); continue;
+ }
+ if (!/^(?:Space|Enter|Arrow(?:Left|Right|Up|Down)|Key[A-Z]|Digit[0-9])$/.test(key.value)) fail(key, 'Unsupported keyboard code');
+ declarations.push({ kind, token, name, key });
+ } else if (Object.hasOwn(VIEW_FIELDS, kind)) {
+ const name = this.expect('name', 'view ID'); this.expect('(');
+ const expressions = [];
+ for (let i = 0; i < VIEW_FIELDS[kind].length; i++) {
+ if (i) { this.newlines(); this.expect(','); }
+ expressions.push(this.expression(0, true));
+ }
+ this.newlines();
+ let color, prefix = '';
+ if (kind !== 'text') {
+ this.expect(','); this.newlines();
+ const value = this.expect('string', 'literal hex color');
+ if (!/^#[0-9a-fA-F]{6}$/.test(value.value)) fail(value, 'Color must use six hexadecimal digits, such as "#356548"');
+ color = value.value;
+ } else if (this.is(',')) { this.take(); this.newlines(); prefix = this.expect('string', 'literal text prefix').value; }
+ this.newlines(); this.expect(')');
+ declarations.push({ kind: 'view', type: kind, token, name, expressions, color, prefix });
+ } else if (kind === 'on') {
+ const event = this.expect('name', 'input name or frame');
+ let edge;
+ if (event.value !== 'frame') {
+ this.expect('.'); edge = this.expect('name', 'down, up, move or cancel');
+ if (!['down', 'up', 'move', 'cancel', 'change'].includes(edge.value)) fail(edge, 'Expected down or up, move, cancel or change');
+ }
+ if (this.is('name', 'use')) {
+ this.take(); const rule = this.expect('name', 'rule name'); this.expect('(');
+ const item = this.expect('name', 'item name or input.target');
+ const argument = this.reference(item); this.expect(')');
+ declarations.push({kind:'handler',token,event,edge,rule,item,argument});
+ } else declarations.push({ kind: 'handler', token, event, edge, body: this.block() });
+ } else fail(token, `Unknown declaration ${kind}`);
+ this.end();
+ }
+ return declarations;
+ }
+}
+
+export function compile(source) {
+ if (typeof source !== 'string') fail({ line: 1, column: 1 }, 'Source must be a string');
+ const sourceBytes = new TextEncoder().encode(source).length;
+ if (sourceBytes > LIMITS.sourceBytes) fail({ line: 1, column: 1 }, 'Source exceeds 32768 UTF-8 bytes');
+ const declarations = new Parser(lex(source)).parse();
+ const program = { states: [], inputs: [], instructions: [], handlers: [], views: [], pointerTargets: [], metrics: {} };
+ const states = new Map(), inputs = new Map(), views = new Set(), keys = new Set(), targets = new Set();
+ const records = new Map(), items = new Map(), rules = new Map();
+ const scalarNames = new Set(declarations.filter(d => d.kind === 'state').map(d => d.name.value));
+ for (const declaration of declarations) {
+ if (!['record','rule'].includes(declaration.kind)) continue;
+ const {name,fields,kind} = declaration, symbols = kind === 'record' ? records : rules;
+ if (RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (kind === 'record') {
+ if (!fields.length || fields.length > 8) fail(name, 'A record needs 1..8 fields');
+ const used = new Set();
+ for (const field of fields) {
+ if (used.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ if (RESERVED.has(field.name.value)) fail(field.name, `Reserved name ${field.name.value}`);
+ used.add(field.name.value);
+ }
+ }
+ symbols.set(name.value, declaration);
+ }
+ let handlerCount = 0;
+ for (const declaration of declarations) {
+ const { kind, name, token } = declaration;
+ if (name && RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (kind === 'record' || kind === 'rule') continue;
+ if (kind === 'item') {
+ if (items.has(name.value) || scalarNames.has(name.value)) fail(name, `Duplicate state/item ${name.value}`);
+ const record = records.get(declaration.type.value);
+ if (!record) fail(declaration.type, `Unknown record ${declaration.type.value}`);
+ const overrides = new Map();
+ for (const field of declaration.fields) {
+ if (!record.fields.some(f => f.name.value === field.name.value)) fail(field.name, `Unknown field ${field.name.value}`);
+ if (overrides.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ overrides.set(field.name.value, field.initial);
+ }
+ const base = states.size;
+ for (const field of record.fields) {
+ if (states.size >= LIMITS.states) fail(name, 'At most 32 states are allowed, including item fields');
+ const qualified = `${name.value}.${field.name.value}`, index = states.size;
+ states.set(qualified,index);
+ program.states.push({name:qualified,initial:overrides.has(field.name.value) ? overrides.get(field.name.value) : field.initial,line:token.line});
+ }
+ items.set(name.value,{type:declaration.type.value,base,count:record.fields.length});
+ } else if (kind === 'state' || kind === 'input') {
+ const symbols = kind === 'state' ? states : inputs;
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (symbols.size >= LIMITS[`${kind}s`]) fail(name, `At most ${LIMITS[`${kind}s`]} ${kind}s are allowed`);
+ symbols.set(name.value, symbols.size);
+ if (kind === 'state') program.states.push({ name: name.value, initial: declaration.initial, line: token.line });
+ else if (declaration.valueInput) {
+ program.inputs.push({name:name.value,kind:'value',line:token.line});
+ } else if (declaration.routes) {
+ if (!declaration.routes.length) fail(name, 'A pointer group needs at least one target');
+ program.inputs.push({name:name.value, routes:[], line:token.line});
+ } else if (declaration.target) {
+ const target = declaration.target;
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ targets.add(target.value);
+ program.inputs.push({ name: name.value, target: target.value, line: token.line });
+ } else {
+ if (keys.has(declaration.key.value)) fail(declaration.key, `Duplicate keyboard code ${declaration.key.value}`);
+ keys.add(declaration.key.value);
+ program.inputs.push({ name: name.value, key: declaration.key.value, line: token.line });
+ }
+ } else if (kind === 'view') {
+ if (views.has(name.value)) fail(name, `Duplicate view ID ${name.value}`);
+ if (views.size >= LIMITS.views) fail(name, 'At most 24 views are allowed');
+ views.add(name.value);
+ } else if (++handlerCount > LIMITS.handlers) fail(token, 'At most 64 handlers are allowed');
+ }
+ for (const declaration of declarations) {
+ if (declaration.target && !views.has(declaration.target.value))
+ fail(declaration.target, `Unknown pointer target ${declaration.target.value}`);
+ }
+ const routedItems = new Set();
+ for (const declaration of declarations) {
+ if (!declaration.routes) continue;
+ const input = inputs.get(declaration.name.value), resolved = program.inputs[input];
+ let type;
+ for (const {target,item:token} of declaration.routes) {
+ if (!views.has(target.value)) fail(target, `Unknown pointer target ${target.value}`);
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ const item = items.get(token.value);
+ if (!item) fail(token, `Unknown item ${token.value}`);
+ if (type && type !== item.type) fail(token, 'Pointer group targets must share one record type');
+ if (routedItems.has(token.value)) fail(token, `Item ${token.value} already has a pointer route`);
+ targets.add(target.value); routedItems.add(token.value); type = item.type;
+ const route = program.pointerTargets.length;
+ if (route >= 24) fail(target, 'At most 24 pointer targets are allowed');
+ program.pointerTargets.push({input,base:item.base,count:item.count});
+ resolved.routes.push({target:target.value, item:token.value, route});
+ }
+ resolved.type = type;
+ }
+ for (const rule of rules.values()) {
+ if (!records.has(rule.type.value)) fail(rule.type, `Unknown record ${rule.type.value}`);
+ if (RESERVED.has(rule.parameter.value)) fail(rule.parameter, `Reserved name ${rule.parameter.value}`);
+ }
+ let pointHandler = false, valueHandler = false;
+ let parameters = null;
+ let parameterPrefix = null;
+ let stack = 0, maxStack = 0;
+ const emit = (op, token, arg = 0, value = 0, delta = 0) => {
+ if (program.instructions.length >= LIMITS.instructions) fail(token, 'At most 512 instructions are allowed');
+ stack += delta;
+ if (stack < 0 || stack > LIMITS.stack) fail(token, 'Expression stack exceeds 64');
+ maxStack = Math.max(maxStack, stack);
+ program.instructions.push({ op, arg, value, line: token.line });
+ };
+ const expression = (node, binding = false) => {
+ const { token } = node;
+ if (node.kind === 'constant') emit(0, token, 0, node.value, 1);
+ else if (node.kind === 'reference') {
+ if (node.name === 'event_value') {
+ if (binding || !valueHandler) fail(token, 'event_value is only available in value change handlers');
+ emit(26, token, 0, 0, 1);
+ } else if (node.name === 'event_x' || node.name === 'event_y') {
+ if (binding || !pointHandler) fail(token, 'event_x and event_y are only available in pointer handlers');
+ emit(node.name === 'event_x' ? 22 : 23, token, 0, 0, 1);
+ } else if (node.name === 'dt') {
+ if (binding) fail(token, 'dt is only available in handlers');
+ emit(2, token, 0, 0, 1);
+ } else {
+ if (parameterPrefix && node.name.startsWith(parameterPrefix) && !parameters.has(node.name))
+ fail(token, `Unknown parameter field ${node.name}`);
+ if (parameters?.has(node.name)) {
+ emit(24, token, parameters.get(node.name), 0, 1);
+ return;
+ }
+ if (!states.has(node.name)) fail(token, `Unknown state ${node.name}`);
+ emit(1, token, states.get(node.name), 0, 1);
+ }
+ } else if (node.kind === 'unary') { expression(node.child, binding); emit(node.op, token); }
+ else if (node.kind === 'binary') {
+ expression(node.left, binding); expression(node.right, binding); emit(node.op, token, 0, 0, -1);
+ } else {
+ for (const arg of node.args) expression(arg, binding);
+ emit(node.op, token, 0, 0, 1 - node.args.length);
+ }
+ };
+ const statements = body => {
+ for (const statement of body) {
+ if (statement.kind === 'assign') {
+ if (parameterPrefix && statement.name.startsWith(parameterPrefix) && !parameters.has(statement.name))
+ fail(statement.token, `Unknown parameter field ${statement.name}`);
+ const parameter = parameters?.get(statement.name);
+ if (parameter === undefined && !states.has(statement.name)) fail(statement.token, `Unknown state ${statement.name}`);
+ expression(statement.expression);
+ emit(parameter === undefined ? 20 : 25, statement.token, parameter === undefined ? states.get(statement.name) : parameter, 0, -1);
+ } else {
+ expression(statement.condition);
+ const branch = program.instructions.length;
+ emit(21, statement.token, 0, 0, -1);
+ statements(statement.body);
+ program.instructions[branch].arg = program.instructions.length;
+ }
+ }
+ };
+ const bodies = new Map();
+ function ruleBody(rule) {
+ if (bodies.has(rule.name.value)) return bodies.get(rule.name.value);
+ parameterPrefix = `${rule.parameter.value}.`;
+ parameters = new Map(records.get(rule.type.value).fields.map((field,index) => [`${rule.parameter.value}.${field.name.value}`,index]));
+ // A shared body may read coordinates; every binding is checked below.
+ pointHandler = true; valueHandler = true; stack = 0;
+ const start = program.instructions.length;
+ statements(rule.body);
+ const length = program.instructions.length - start;
+ const point = program.instructions.slice(start).some(op => op.op === 22 || op.op === 23);
+ parameters = null; parameterPrefix = null;
+ const value = program.instructions.slice(start).some(op => op.op === 26);
+ const body = {start,length,point,value}; bodies.set(rule.name.value,body); return body;
+ }
+ for (const declaration of declarations) {
+ if (declaration.kind === 'handler') {
+ let event = 0;
+ pointHandler = false; valueHandler = false;
+ if (declaration.event.value !== 'frame') {
+ if (!inputs.has(declaration.event.value)) fail(declaration.event, `Unknown input ${declaration.event.value}`);
+ const index = inputs.get(declaration.event.value), edge = declaration.edge.value;
+ pointHandler = Boolean(program.inputs[index].target || program.inputs[index].routes);
+ valueHandler = program.inputs[index].kind === 'value';
+ if (valueHandler !== (edge === 'change')) fail(declaration.edge, 'Value inputs require change; change requires a value input');
+ if (!pointHandler && (edge === 'move' || edge === 'cancel')) fail(declaration.edge, 'move and cancel require a pointer input');
+ event = edge === 'change' ? 33 + index : edge === 'move' ? 17 + index : edge === 'cancel' ? 25 + index : 1 + index * 2 + (edge === 'up' ? 1 : 0);
+ }
+ if (declaration.rule) {
+ const rule = rules.get(declaration.rule.value);
+ const routed = declaration.argument.includes('.');
+ const input = program.inputs[inputs.get(declaration.event.value)];
+ if (routed && (!input?.routes || declaration.argument !== `${declaration.event.value}.target`))
+ fail(declaration.item, 'Use the current pointer group target');
+ const item = routed ? {type:input.type, count:records.get(input.type).fields.length} : items.get(declaration.item.value);
+ if (!rule) fail(declaration.rule, `Unknown rule ${declaration.rule.value}`);
+ if (!item) fail(declaration.item, `Unknown item ${declaration.item.value}`);
+ if (item.type !== rule.type.value) fail(declaration.item, `Rule ${rule.name.value} requires ${rule.type.value}`);
+ const pointer = pointHandler, value = valueHandler;
+ const body = ruleBody(rule);
+ if (body.value && !value) fail(declaration.rule, 'Value-reading rules require a value input');
+ if (body.point && !pointer) fail(declaration.rule, 'Coordinate-reading rules require a pointer input');
+ program.handlers.push({event,start:body.start,length:body.length,line:declaration.token.line,parameterBase:routed ? 255 : item.base,parameterCount:item.count});
+ } else {
+ const start = program.instructions.length;
+ stack = 0; statements(declaration.body);
+ program.handlers.push({ event, start, length: program.instructions.length - start, line: declaration.token.line });
+ }
+ } else if (declaration.kind === 'view') {
+ const view = { id: declaration.name.value, type: declaration.type, line: declaration.token.line, bindings: {} };
+ if (view.type === 'text') view.prefix = declaration.prefix;
+ else view.color = declaration.color;
+ declaration.expressions.forEach((node, index) => {
+ const start = program.instructions.length;
+ stack = 0; expression(node, true);
+ view.bindings[VIEW_FIELDS[view.type][index]] = { start, length: program.instructions.length - start };
+ });
+ program.views.push(view);
+ }
+ }
+ // Unused definitions still receive name/type checking, but reserve no VM body.
+ for (const rule of rules.values()) {
+ if (bodies.has(rule.name.value)) continue;
+ const instructions = program.instructions, previousMax = maxStack;
+ program.instructions = [];
+ ruleBody(rule);
+ program.instructions = instructions; maxStack = previousMax;
+ }
+ program.metrics = { sourceBytes, sourceLines: source === '' ? 0 : source.split('\n').length,
+ states: states.size, inputs: inputs.size, views: views.size,
+ handlers: program.handlers.length, instructions: program.instructions.length, maxStack };
+ return program;
+}
+
+export { LIMITS };
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/core.wasm b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/core.wasm
new file mode 100644
index 0000000..79c50a8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/core.wasm
Binary files differ
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/project.mjs b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/project.mjs
new file mode 100644
index 0000000..861e0fc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/project.mjs
@@ -0,0 +1,47 @@
+import { compile } from './compiler.mjs';
+
+// Two escaped source strings plus up to 32 generated item.field names. A long
+// schema field can appear in every item without repeating in the source text.
+export const MAX_PROJECT_BYTES = (2 * 6 + 32) * 32768 + 8192;
+const encoder = new TextEncoder();
+function sourceText(value, label) {
+ if (typeof value !== 'string' || encoder.encode(value).length > 32768)
+ throw new Error(`${label}: UTF-8 32 KiB 이하의 코드가 필요합니다.`);
+ return value;
+}
+
+// No runtime mutation. Validate every saved value before opening core staging.
+export function validateDocument(document) {
+ if (!document || typeof document !== 'object' || Array.isArray(document) ||
+ document.format !== 'pure-workbench' || document.version !== 2)
+ throw new Error('배치 파일 형식이 맞지 않습니다. pure-workbench version 2가 필요합니다.');
+ const source = sourceText(document.source, '적용된 코드');
+ const draft = sourceText(Object.hasOwn(document, 'draft') ? document.draft : source, '편집 중인 코드');
+ const program = compile(source);
+ if (!Array.isArray(document.states) || document.states.length !== program.states.length)
+ throw new Error('저장된 상태 목록이 적용된 코드와 일치하지 않습니다.');
+ const values = new Map();
+ for (const entry of document.states) {
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry) || typeof entry.name !== 'string' || values.has(entry.name))
+ throw new Error('상태 이름이 잘못됐거나 중복됐습니다.');
+ const value = entry.value === '-0' ? -0 : entry.value;
+ if (typeof value !== 'number' || !Number.isFinite(value)) throw new Error('상태 값은 유한한 숫자여야 합니다.');
+ values.set(entry.name, value);
+ }
+ for (const state of program.states)
+ if (!values.has(state.name)) throw new Error(`저장된 상태가 없습니다: ${state.name}`);
+ return { source, draft, program, values: program.states.map(state => values.get(state.name)) };
+}
+
+export function parseProject(text) {
+ if (typeof text !== 'string' || encoder.encode(text).length > MAX_PROJECT_BYTES)
+ throw new Error('작업 파일이 너무 큽니다.');
+ let project;
+ try { project = JSON.parse(text); } catch { throw new Error('올바른 JSON 파일이 아닙니다.'); }
+ if (!project || typeof project !== 'object' || Array.isArray(project) || project.format !== 'pure-workbench')
+ throw new Error('Pure 작업물 형식이 아닙니다.');
+ if (project.version === 1) sourceText(project.source, '코드');
+ else if (project.version === 2) validateDocument(project);
+ else throw new Error('지원하지 않는 작업 파일 버전입니다.');
+ return project;
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/runtime.mjs b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/runtime.mjs
new file mode 100644
index 0000000..d8d6618
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/sources/prototypes/workbench/web/runtime.mjs
@@ -0,0 +1,350 @@
+import { compile } from './compiler.mjs';
+import { validateDocument } from './project.mjs';
+
+const messages = [
+ '', '실행기의 용량 한도를 넘었습니다.', '실행 정의가 유효하지 않습니다.',
+ '계산 스택의 범위를 벗어났습니다.', '0으로 나눌 수 없습니다.',
+ '계산 결과가 유한한 수의 범위를 벗어났습니다.', '조건 분기 범위가 유효하지 않습니다.',
+ '존재하지 않는 상태를 참조했습니다.', '시간 간격이 유효하지 않습니다.',
+ '정의되지 않은 입력 사건입니다.',
+];
+const sourceLimit = 32768;
+
+function problem(message, line = null, column = null) {
+ return Object.assign(new Error(message), { line, column });
+}
+
+function freezeProgram(value) {
+ if (value && typeof value === 'object') {
+ for (const child of Object.values(value)) freezeProgram(child);
+ Object.freeze(value);
+ }
+ return value;
+}
+
+export async function createRuntime(wasmBytes, evaluationOptions = {}) {
+ if (wasmBytes === undefined) {
+ const response = await fetch(new URL('./core.wasm', import.meta.url), { cache: 'no-store' });
+ if (!response.ok) throw new Error(`실행기를 불러오지 못했습니다 (HTTP ${response.status}).`);
+ wasmBytes = await response.arrayBuffer();
+ }
+ const module = await WebAssembly.compile(wasmBytes);
+ if (WebAssembly.Module.imports(module).length) throw new Error('이 실행기는 호스트 함수 없이 동작해야 합니다.');
+ const { exports: core } = await WebAssembly.instantiate(module, {});
+ if (typeof core.eval_bounded !== 'function' || typeof core.abort_program !== 'function' || typeof core.dispatch_point !== 'function' || typeof core.put_restored_value !== 'function' || typeof core.commit_restored_program !== 'function' || typeof core.bind_handler !== 'function' || typeof core.put_pointer_target !== 'function' || typeof core.bind_target_handler !== 'function' || typeof core.dispatch_target !== 'function' || typeof core.dispatch_value !== 'function')
+ throw new Error('실행기 버전이 맞지 않습니다. 새로고침하거나 core.wasm을 다시 빌드하세요.');
+ core.reset_all();
+ let program = null;
+ let appliedSource = '';
+ let lastEvent = null;
+ // Keep a failed event visible through its release/focus-loss cleanup.
+ // The active program can clear this diagnostic by apply or explicit reset.
+ let lastFailure = null;
+ const held = new Map();
+ const points = new Map();
+ let presenting = false;
+ let bindings = [];
+ let pointRoutes = new Map();
+ // One bounded publication buffer, never exposed to callers. No state mirror.
+ let displayValues = null, displayValid = null;
+ function available() {
+ if (presenting) throw new Error('출력 전달 중에는 실행기를 다시 호출할 수 없습니다.');
+ }
+ let evaluationPolicy = { cacheEntries: 0, historyEntries: 8, workLimit: 2048 };
+
+ function checked(code, line = null) {
+ if (code !== 0) throw problem(messages[code] || `실행기 오류 ${code}`, line);
+ }
+ function inputIndex(name) {
+ const index = program?.inputs.findIndex((input) => input.name === name) ?? -1;
+ if (index < 0) throw new Error(`정의되지 않은 입력: ${name}`);
+ return index;
+ }
+ function dispatch(event, name, phase, source, point = null, value = undefined) {
+ const status = value !== undefined ? core.dispatch_value(event, value) : point ? (point.route === undefined ? core.dispatch_point(event, point.x, point.y)
+ : core.dispatch_target(event, point.route, point.x, point.y)) : core.dispatch(event, event === 0 ? 1 / 60 : 0);
+ const pc = core.info(2) >>> 0;
+ lastEvent = { name, phase, source, status,
+ line: program?.instructions[pc]?.line ?? null, ops: core.info(3) >>> 0 };
+ if (point) { lastEvent.x = point.x; lastEvent.y = point.y; if (point.target) lastEvent.target = point.target; }
+ if (value !== undefined) lastEvent.value = value;
+ if (status) lastFailure = { ...lastEvent };
+ return status;
+ }
+
+ function evaluateDisplay() {
+ core.begin_evaluation(evaluationPolicy.workLimit);
+ if (!bindings.length) return null;
+ displayValues ??= new Float64Array(96);
+ displayValid ??= new Uint8Array(24);
+ let error = null, slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ displayValid[i] = 1;
+ for (const [name, binding] of bindings[i]) {
+ const value = core.eval_bounded(binding.start, binding.length);
+ if (core.evaluation_info(0) === 10) {
+ displayValid.fill(0);
+ return { code: 101, line: view.line,
+ message: '표시 계산의 작업량 한도를 넘었습니다. 한도를 늘리거나 표시식을 줄이세요.' };
+ }
+ if (!Number.isFinite(value) || ((name === 'width' || name === 'height' || name === 'radius') && value < 0)) {
+ error ??= { line: view.line, message: `${view.id}.${name}: 표시할 수 없는 값입니다. 0 나눗셈이나 음수 크기를 확인하세요.` };
+ displayValid[i] = 0;
+ }
+ displayValues[slot++] = value;
+ }
+ }
+ return error;
+ }
+
+ function status(viewError) {
+ const executionError = lastFailure?.status || 0;
+ return {
+ tick: core.info(0) >>> 0, revision: core.info(4) >>> 0,
+ displayError: viewError ? { code: viewError.code || 100, ...viewError } : null,
+ lastError: executionError || (viewError ? viewError.code || 100 : 0),
+ errorMessage: executionError ? messages[executionError] || `실행 오류 ${executionError}` : viewError?.message || '',
+ errorLine: executionError ? lastFailure.line : viewError?.line ?? null,
+ lastOps: core.info(3) >>> 0, successfulEvents: core.info(9) >>> 0,
+ held: [...held.keys()], lastEvent: lastEvent ? { ...lastEvent } : null,
+ lastFailure: lastFailure ? { ...lastFailure } : null,
+ memory: {
+ linearBytes: core.memory.buffer.byteLength,
+ reservedEngineBytes: core.layout(0), programReservedBytes: core.layout(1),
+ instructionBytes: core.layout(2), handlerBytes: core.layout(3),
+ activeIRBytes: core.layout(4), activeStateBytes: core.layout(5),
+ stagingReservedBytes: core.layout(6), evalStackBytes: core.layout(7),
+ pointerTargetBytes: core.layout(8), pointerTargets: core.layout(9),
+ },
+ };
+ }
+
+ function load(next, source, restored = null) {
+ const oldIds = new Map(restored ? [] : program?.states.map((state, index) => [state.name, index]) ?? []);
+ checked(core.begin_program(next.states.length, next.inputs.length));
+ try {
+ for (let index = 0; index < next.states.length; index++) {
+ const state = next.states[index];
+ checked(core.put_state(index, state.initial, oldIds.get(state.name) ?? -1), state.line);
+ if (restored) checked(core.put_restored_value(index, restored[index]), state.line);
+ }
+ for (const op of next.instructions) checked(core.put_instruction(op.op, op.arg, op.value), op.line);
+ for (const target of next.pointerTargets) checked(core.put_pointer_target(target.input, target.base, target.count));
+ for (const [index, handler] of next.handlers.entries()) {
+ checked(core.put_handler(handler.event, handler.start, handler.length), handler.line);
+ if (handler.parameterCount)
+ checked(handler.parameterBase === 255 ? core.bind_target_handler(index, handler.parameterCount)
+ : core.bind_handler(index, handler.parameterBase, handler.parameterCount), handler.line);
+ }
+ checked(restored ? core.commit_restored_program() : core.commit_program());
+ } catch (error) {
+ core.abort_program();
+ throw error;
+ }
+ pointRoutes = new Map(next.inputs.flatMap(input => (input.routes ?? []).map(route => [route.target, route])));
+ program = next;
+ bindings = next.views.map(view => Object.entries(view.bindings));
+ appliedSource = source;
+ lastEvent = null;
+ lastFailure = null;
+ }
+
+ const api = {
+ get currentProgram() { return program; },
+ configureEvaluation({ cacheEntries = evaluationPolicy.cacheEntries,
+ historyEntries = evaluationPolicy.historyEntries, workLimit = evaluationPolicy.workLimit } = {}) {
+ available();
+ for (const [name, value, maximum] of [['cacheEntries', cacheEntries, 32],
+ ['historyEntries', historyEntries, 8], ['workLimit', workLimit, 0xffffffff]]) {
+ if (!Number.isInteger(value) || value < 0 || value > maximum)
+ throw new Error(`${name}: 0~${maximum} 사이의 정수여야 합니다.`);
+ }
+ checked(core.configure_evaluation(cacheEntries, historyEntries));
+ evaluationPolicy = { cacheEntries, historyEntries, workLimit };
+ return { ...evaluationPolicy };
+ },
+ forgetEvaluation(part = 'all') {
+ available();
+ const flags = part === 'all' ? 3 : part === 'values' ? 1 : part === 'history' ? 2 : undefined;
+ if (flags === undefined) throw new Error('삭제할 기록은 values, history, all 중 하나여야 합니다.');
+ core.forget_evaluation(flags);
+ },
+ evaluationStats() {
+ return { ...evaluationPolicy, work: core.evaluation_info(1),
+ instructions: core.evaluation_info(2), cacheHits: core.evaluation_info(3),
+ reservedBytes: core.evaluation_info(6), dedicatedBytes: core.evaluation_info(7),
+ sharedBytes: core.evaluation_info(8), reuseAvailable: Boolean(core.evaluation_info(9)),
+ workspaceTagBytes: core.evaluation_info(10) };
+ },
+ apply(source) {
+ available();
+ if (typeof source !== 'string' || new TextEncoder().encode(source).length > sourceLimit) {
+ throw problem('정의는 UTF-8 기준 32,768바이트 이하의 텍스트여야 합니다.');
+ }
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 적용하세요. 현재 작업은 그대로 유지합니다.');
+ const next = freezeProgram(compile(source));
+ load(next, source);
+ return next;
+ },
+ restoreDocument(document) {
+ available();
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 복원하세요.');
+ const next = validateDocument(document);
+ load(freezeProgram(next.program), next.source, next.values);
+ return { source: next.source, draft: next.draft };
+ },
+ exportDocument(draft = appliedSource) {
+ available();
+ if (!program) throw problem('먼저 코드를 적용하세요.');
+ if (held.size) throw problem('조작을 끝낸 뒤 배치를 저장하세요.');
+ if (lastFailure) throw problem('실행 오류를 해결한 뒤 배치를 저장하세요.');
+ if (typeof draft !== 'string' || new TextEncoder().encode(draft).length > sourceLimit)
+ throw problem('편집 중인 코드는 UTF-8 32 KiB 이하여야 합니다.');
+ return { format: 'pure-workbench', version: 2, source: appliedSource, draft,
+ states: program.states.map((state, i) => {
+ const value = core.get_state(i);
+ return { name: state.name, value: Object.is(value, -0) ? '-0' : value };
+ }) };
+ },
+ reset() {
+ available();
+ held.clear();
+ points.clear();
+ core.reset_state();
+ lastEvent = null;
+ lastFailure = null;
+ },
+ frame(count = 1) {
+ available();
+ if (!Number.isInteger(count) || count < 0 || count > 600) throw new Error('프레임 수는 0~600 사이의 정수여야 합니다.');
+ if (!program) return 0;
+ for (let i = 0; i < count; i++) {
+ const code = dispatch(0, 'frame', 'frame', 'clock');
+ if (code !== 0) return code;
+ }
+ return 0;
+ },
+ down(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name) || new Set();
+ if (sources.has(source)) return 0;
+ const wasDown = sources.size > 0;
+ sources.add(source);
+ held.set(name, sources);
+ return wasDown ? 0 : dispatch(1 + index * 2, name, 'down', source);
+ },
+ up(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name);
+ if (!sources?.delete(source)) return 0;
+ if (sources.size) return 0;
+ held.delete(name);
+ return dispatch(2 + index * 2, name, 'up', source);
+ },
+ change(name, value, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind !== 'value') throw new Error('숫자 값에 연결된 입력이 아닙니다.');
+ if (!Number.isFinite(value)) throw new Error('입력 값은 유한한 숫자여야 합니다.');
+ return dispatch(33 + index, name, 'change', source, null, value);
+ },
+ point(name, phase, x, y, source = 'external', target = undefined) {
+ available();
+ const index = inputIndex(name);
+ const input = program.inputs[index];
+ if (!input.target && !input.routes) throw new Error('포인터에 연결된 입력이 아닙니다.');
+ const route = input.routes ? pointRoutes.get(target) : undefined;
+ if (input.routes && (!route || program.pointerTargets[route.route].input !== index)) throw new Error('포인터 그룹에 연결된 도형 이름이 필요합니다.');
+ if (!input.routes && target !== undefined) throw new Error('단일 포인터 입력에는 대상 인자를 지정하지 않습니다.');
+ const owner = route ? `${name}:${target}` : name;
+ if (!['down', 'move', 'up', 'cancel'].includes(phase)) throw new Error('포인터 단계는 down, move, up, cancel 중 하나여야 합니다.');
+ if (!Number.isFinite(x) || !Number.isFinite(y)) throw new Error('포인터 좌표는 유한한 숫자여야 합니다.');
+ if (typeof source !== 'string' || source.length === 0) throw new Error('포인터 출처 이름이 필요합니다.');
+ let point = points.get(owner);
+ if (phase === 'down') {
+ if (point?.source === source) return 0;
+ if (point) throw new Error('이 입력은 다른 포인터가 사용 중입니다.');
+ point = {name, source, x, y, target, route:route?.route};
+ points.set(owner, point);
+ held.set(owner, new Set([source]));
+ } else {
+ if (!point || point.source !== source) return 0;
+ point.x = x; point.y = y;
+ if (phase === 'up' || phase === 'cancel') { points.delete(owner); held.delete(owner); }
+ }
+ const event = phase === 'move' ? 17 + index : phase === 'cancel' ? 25 + index : 1 + index * 2 + (phase === 'up' ? 1 : 0);
+ return dispatch(event, name, phase, source, point);
+ },
+ releaseAll() {
+ available();
+ let firstError = 0;
+ for (const point of [...points.values()]) {
+ const status = api.point(point.name, 'cancel', point.x, point.y, point.source, point.target);
+ if (!firstError) firstError = status;
+ }
+ for (const [name, sources] of [...held]) {
+ for (const source of [...sources]) {
+ const status = api.up(name, source);
+ if (!firstError) firstError = status;
+ }
+ }
+ return firstError;
+ },
+ exportProject() {
+ return { format: 'pure-workbench', version: 1, source: appliedSource };
+ },
+ // Synchronous trusted output adapter. Callbacks run only after the whole
+ // display has been evaluated. Runtime mutation/reentrant reads are refused.
+ // Exceptions from an adapter propagate; the next call republishes all values.
+ present(target) {
+ available();
+ presenting = true;
+ try {
+ const { begin, state, view, value, end } = target;
+ for (const callback of [begin, state, view, value, end])
+ if (typeof callback !== 'function') throw new TypeError('출력 어댑터 함수가 필요합니다.');
+ const error = evaluateDisplay();
+ begin.call(target, program);
+ for (let i = 0; i < (program?.states.length ?? 0); i++) state.call(target, i, core.get_state(i));
+ let slot = 0, visible = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const valid = Boolean(displayValid[i]);
+ view.call(target, i, valid);
+ for (const [name] of bindings[i]) {
+ if (valid) value.call(target, i, name, displayValues[slot]);
+ slot++;
+ }
+ if (valid) visible++;
+ }
+ end.call(target, visible);
+ return status(error);
+ } finally { presenting = false; }
+ },
+ snapshot() {
+ available();
+ const error = evaluateDisplay();
+ const states = Object.fromEntries((program?.states ?? []).map((state, index) => [state.name, core.get_state(index)]));
+ const views = [];
+ let slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ const rendered = displayValid[i] ? { id: view.id, type: view.type, color: view.color, prefix: view.prefix } : null;
+ for (const [name] of bindings[i]) {
+ if (rendered) rendered[name] = displayValues[slot];
+ slot++;
+ }
+ if (rendered) views.push(rendered);
+ }
+ return { states, views, ...status(error) };
+ },
+ };
+ api.configureEvaluation(evaluationOptions);
+ return Object.freeze(api);
+}
diff --git a/prototypes/connections/results/2026-09-23-native-connections/verification.json b/prototypes/connections/results/2026-09-23-native-connections/verification.json
new file mode 100644
index 0000000..3a8b2cc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-native-connections/verification.json
@@ -0,0 +1,29 @@
+{
+ "scope": "Correctness, lifetimes, admission bounds; no throughput, latency, or RSS comparison",
+ "compiler": "cc (Debian 14.2.0-19) 14.2.0",
+ "native_command": "make check EVIDENCE=results/2026-09-23-native-connections/native.json",
+ "sanitized_command": "make check BUILD=build/sanitized CFLAGS='-std=c17 -O1 -g -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer' EVIDENCE=results/2026-09-23-native-connections/sanitized.json",
+ "core_checks": {
+ "native": "passed",
+ "asan_ubsan": "passed",
+ "leak_detection_disabled": false
+ },
+ "integration_scenarios_each": 15,
+ "cli_regression": {
+ "command": "node --test cli.test.mjs",
+ "cwd": "prototypes/workbench",
+ "passed": 8,
+ "failed": 0,
+ "test_sha256": "7e4688824e26dc7e56396f9d4d62726de0ccb1490e1a388bb64690ae2aae52f4"
+ },
+ "source_hashes_equal": true,
+ "source_snapshots": "sources/",
+ "final_binaries_match_records": true,
+ "limitations": [
+ "SQLite shared library was not rebuilt with sanitizers",
+ "Linux AArch64 only; no macOS execution",
+ "Bounded payload retention excludes SQLite internals, OS socket buffers and client allocations",
+ "SQLite operations remain synchronous; absolute deadlines are enforced between those operations",
+ "Native connection path is fixed in C; Pure-authored external effects are not implemented"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/README.md b/prototypes/connections/results/2026-09-23-prepared-connections/README.md
new file mode 100644
index 0000000..c79e954
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/README.md
@@ -0,0 +1,31 @@
+# 020 검증 자료
+
+> 필드와 데이터 의존 범위 도입 후 기록은 [021](../2026-09-23-field-connections/README.md)에 있다.
+> 이 디렉터리의 원자료·소스 사본은 상수 구간 프로파일 당시의 결과로 보존한다.
+
+작성한 구간·저장·응답 관계를 준비하고 실제 네이티브 TCP 경로에서 실행한 기록이다.
+속도·처리량·RSS 비교는 하지 않았다.
+
+- [native.json](native.json): 일반 빌드의 22개 통합 시나리오, 준비 결과, 종료 자원, 실행 파일·소스 해시.
+- [sanitized.json](sanitized.json): ASan·UBSan 빌드의 같은 검사. 누수 검사를 끄지 않았다.
+- [verification.json](verification.json): 명령, 저장/전송 및 준비 단위 검사 결과, 소스·바이너리 일치 확인.
+- `sources/`: 기록된 파일의 사본. 현재 작업 트리가 바뀐 뒤에는 별도 작업 트리에 배치해 재현한다.
+
+`prepared_connections`는 검사 시 작성한 정의에서 나온 구간·길이 조건이다.
+`runtime_view_steps`는 요청별 뷰 노드 실행기가 없다는 구조 설명값이고 시간이나 CPU 명령
+계측값은 아니다. `prepared_program_bytes`는 준비 구조체 하나의 `sizeof`다. 전체 메모리와
+혼동하지 않는다. 부모 구간이나 쓰지 않는 구간도 유효해야 하므로 최소 원본 길이가 최종
+응답 범위보다 클 수 있다.
+
+논리적 본문 예산 16 B로 1 MiB 파일에서 작성한 16 B를 응답한 검사는 요구 범위 전달을
+확인한다. mmap의 페이지·정렬 비용, 파일 보유 공간, OS 버퍼, 전체 RSS는 이 예산 밖이다.
+입력의 일부를 응답하는 경우에는 원본 수신 할당 전체를 유지·계상한다.
+
+기존 저장 단위 검사 외에 `test-program`은 준비 결과를 순차 범위 검사와 대조하며,
+잘못된 이름·타입·효과 위치·상수 범위·소스 한도 등을 거절하는지 확인한다. 기본 작성 파일로
+기존 Workbench 조작·저장·새 실행기 복원이 유지되는 것도 통합 검사에 포함했다.
+
+재현은 [구현 README](../../README.md)의 `make check`를 따른다.
+`EVIDENCE=/새/경로.json`으로 원자료를 기록하며 기존 파일을 덮어쓰지 않는다. 이 환경은
+소켓·자식 프로세스·LeakSanitizer 제한 때문에 승인된 환경에서 로컬 검사를 실행했다.
+외부 서비스는 사용하지 않았으며 macOS와 실제 전원 장애는 확인하지 않았다.
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/native.json b/prototypes/connections/results/2026-09-23-prepared-connections/native.json
new file mode 100644
index 0000000..4e04783
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/native.json
@@ -0,0 +1,269 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "whole": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "whole": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "prepared_program_bytes": 112
+ },
+ "write": {
+ "read": {
+ "whole": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "whole": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "prepared_program_bytes": 112
+ }
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 11,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115417,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 39288
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "binary_sha256": "ce76b1ff164623c8575c8c313a97ec4083c8a500eef88ab49072bc2e04d7520d",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "7a506fb79a074f0d90eaa6f047a364e4fee28eea9ebea1f869dbd3770edc6a2e",
+ "prototypes/connections/store.h": "05c5a4e35e27a4d309c3209c84112fd38d65093ece79ddc4eb1b68adb8e5741f",
+ "prototypes/connections/program.c": "b6b848b261aa9da455126ec25fff0494b4eefb649ce0fd036f075c1efb41f9c8",
+ "prototypes/connections/program.h": "700880cba88b18b08c1b87aa4da46fedc81f3d665d74e40fc659095fe4c3f014",
+ "prototypes/connections/server.c": "d2cb3cc8d47cb5e6bf258cf62c70c039b5c5e945fa5c4d5edb7917d50395fe73",
+ "prototypes/connections/check.py": "7321ba3a48a10a7d1344bbf61df3fb693e9ac95e00d26d3d247bd6a39997505f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "d58248c65d59fa31f37ba50aa9ad761d3e9698d1e17d61307b7e88089c70d385",
+ "prototypes/connections/Makefile": "85bc73e364fb5a273efd7bfbd2e8118091f634d0e263d0729bea445252dcd7f0",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sanitized.json b/prototypes/connections/results/2026-09-23-prepared-connections/sanitized.json
new file mode 100644
index 0000000..d5cc604
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sanitized.json
@@ -0,0 +1,269 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "whole": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "whole": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "prepared_program_bytes": 112
+ },
+ "write": {
+ "read": {
+ "whole": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "whole": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "prepared_program_bytes": 112
+ }
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 39288
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 39288
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "binary_sha256": "3cb873b98d64992cc89f11186de1e97baf19fd7aa3fcb5784b061bea7828b206",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "7a506fb79a074f0d90eaa6f047a364e4fee28eea9ebea1f869dbd3770edc6a2e",
+ "prototypes/connections/store.h": "05c5a4e35e27a4d309c3209c84112fd38d65093ece79ddc4eb1b68adb8e5741f",
+ "prototypes/connections/program.c": "b6b848b261aa9da455126ec25fff0494b4eefb649ce0fd036f075c1efb41f9c8",
+ "prototypes/connections/program.h": "700880cba88b18b08c1b87aa4da46fedc81f3d665d74e40fc659095fe4c3f014",
+ "prototypes/connections/server.c": "d2cb3cc8d47cb5e6bf258cf62c70c039b5c5e945fa5c4d5edb7917d50395fe73",
+ "prototypes/connections/check.py": "7321ba3a48a10a7d1344bbf61df3fb693e9ac95e00d26d3d247bd6a39997505f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "d58248c65d59fa31f37ba50aa9ad761d3e9698d1e17d61307b7e88089c70d385",
+ "prototypes/connections/Makefile": "85bc73e364fb5a273efd7bfbd2e8118091f634d0e263d0729bea445252dcd7f0",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "9f760e4a2ce6ea11f2be07693fceca74088884885cc545a70ceef5003d0b2479",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/Makefile b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/Makefile
new file mode 100644
index 0000000..50ad1cb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/Makefile
@@ -0,0 +1,24 @@
+CC ?= cc
+CFLAGS ?= -O2 -g
+CFLAGS += -std=c17 -Wall -Wextra -Wpedantic -Werror
+BUILD ?= build
+
+.PHONY: all check
+all: $(BUILD)/pure-connections
+
+$(BUILD):
+ mkdir -p $@
+
+$(BUILD)/pure-connections: server.c store.c flow.c program.c store.h flow.h program.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) server.c store.c flow.c program.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-flow: test-flow.c store.c flow.c store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) -DPURE_STORE_TEST test-flow.c store.c flow.c $(LDFLAGS) $(LDLIBS) -o $@
+
+$(BUILD)/test-program: test-program.c program.c program.h store.h flow.h | $(BUILD)
+ $(CC) $(CPPFLAGS) $(CFLAGS) test-program.c program.c $(LDFLAGS) $(LDLIBS) -o $@
+
+check: $(BUILD)/test-flow $(BUILD)/test-program $(BUILD)/pure-connections
+ $(BUILD)/test-flow
+ $(BUILD)/test-program
+ python3 check.py --server $(BUILD)/pure-connections $(if $(EVIDENCE),--output "$(EVIDENCE)")
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/check.py b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/check.py
new file mode 100644
index 0000000..c547ebf
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/check.py
@@ -0,0 +1,419 @@
+#!/usr/bin/env python3
+"""Exercise local TCP, immutable byte extents, and the existing workbench CLI."""
+import argparse
+from contextlib import contextmanager
+from concurrent.futures import ThreadPoolExecutor
+import fcntl
+import hashlib
+import http.client
+import json
+import platform
+from pathlib import Path
+import select
+import socket
+import struct
+import subprocess
+import tempfile
+import time
+
+ROOT = Path(__file__).resolve().parent
+WORKBENCH = ROOT.parent / 'workbench'
+OBJECT_LIMIT = (2 * 6 + 32) * 32768 + 8192
+
+
+class Server:
+ def __init__(self, binary, storage, budget=4 * 1024 * 1024, timeout=5000, program=None):
+ self.process = subprocess.Popen([str(binary), '--store', str(storage), '--port', '0',
+ '--program', str(program or ROOT / 'examples/storage.pure'),
+ '--budget', str(budget), '--timeout-ms', str(timeout), '--send-buffer', '4096'],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
+ if not select.select([self.process.stdout], [], [], 15)[0]:
+ self.process.kill()
+ raise AssertionError('server readiness timed out')
+ line = self.process.stdout.readline()
+ if not line:
+ raise AssertionError(self.process.communicate(timeout=5))
+ self.ready = json.loads(line)
+ self.port = self.ready['port']
+ self.stats = None
+
+ def close(self):
+ if self.process.poll() is None:
+ self.process.terminate()
+ try:
+ stdout, stderr = self.process.communicate(timeout=10)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ self.process.communicate()
+ raise
+ assert self.process.returncode == 0, (stdout, stderr)
+ self.stats = json.loads(stderr)
+ assert self.stats['active'] == self.stats['retained_payload_bytes'] == 0
+ assert self.stats['peak_retained_payload_bytes'] <= self.stats['payload_budget']
+ assert self.stats['peak_connections'] <= 8
+
+
+@contextmanager
+def serving(*args, **kwargs):
+ server = Server(*args, **kwargs)
+ try:
+ yield server
+ finally:
+ server.close()
+
+
+def rpc(server, method, key, body=b'', expected=None):
+ headers = {'Content-Length': str(len(body))}
+ if expected is not None:
+ headers['If-None-Match' if expected == 0 else 'If-Match'] = '*' if expected == 0 else f'"{expected}"'
+ connection = http.client.HTTPConnection('127.0.0.1', server.port, timeout=8)
+ try:
+ connection.request(method, f'/objects/{key}', body, headers)
+ response = connection.getresponse()
+ return response.status, dict(response.getheaders()), response.read()
+ finally:
+ connection.close()
+
+
+def wire(server, request, chunks=None):
+ with socket.create_connection(('127.0.0.1', server.port), timeout=8) as sock:
+ if chunks:
+ for chunk in chunks:
+ sock.sendall(chunk)
+ else:
+ sock.sendall(request)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ return response.status, dict(response.getheaders()), response.read()
+
+
+def header(method, key, size=0, condition=b''):
+ return (f'{method} /objects/{key} HTTP/1.1\r\nHost: localhost\r\n'
+ f'Content-Length: {size}\r\n'.encode() + condition + b'\r\n')
+
+
+def cli(server, commands, source=None, expected_code=0):
+ result = subprocess.run(['node', str(WORKBENCH / 'cli.mjs'), *([str(source)] if source else [])],
+ input=commands.replace('$URL', f'http://127.0.0.1:{server.port}'), text=True,
+ capture_output=True, timeout=30)
+ assert result.returncode == expected_code, (result.stdout, result.stderr)
+ return [json.loads(line) for line in result.stdout.splitlines()], result.stderr
+
+
+def check(binary, directory):
+ storage = directory / 'objects'
+ checks, records = [], []
+ with serving(binary, storage) as server:
+ assert rpc(server, 'GET', 'absent')[0] == 404
+ payload = b'\x00\xffbinary\r\n\r\n' + bytes(range(256)) * 41
+ request = header('PUT', 'binary', len(payload), b'If-None-Match: *\r\n') + payload
+ status, headers, _ = wire(server, request, [request[:7], request[7:51], request[51:57], request[57:]])
+ assert status == 200 and headers['ETag'] == '"1"'
+ assert rpc(server, 'GET', 'binary')[2] == payload
+ checks.append('fragmented request and binary bytes round trip')
+ assert rpc(server, 'PUT', 'binary', b'new', 0)[0] == 412
+ assert rpc(server, 'PUT', 'binary', b'new', 1)[0] == 200
+ assert rpc(server, 'PUT', 'binary', b'stale', 1)[0] == 412
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('conditional create and stale revision preserve committed bytes')
+
+ with (storage / '.writer.lock').open('r+b') as lock:
+ fcntl.lockf(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ assert rpc(server, 'PUT', 'binary', b'blocked', 2)[0] == 503
+ fcntl.lockf(lock, fcntl.LOCK_UN)
+ broken = storage / 'obj-broken'
+ broken.write_bytes(b'incomplete')
+ assert rpc(server, 'GET', 'broken')[0] == 500
+ assert rpc(server, 'PUT', 'broken', b'failure', 0)[0] == 500
+ assert broken.read_bytes() == b'incomplete'
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('writer contention and invalid extent fail without overwriting data')
+
+ with serving(binary, storage) as second_writer:
+ with ThreadPoolExecutor(max_workers=2) as pool:
+ tasks = [pool.submit(rpc, target, 'PUT', 'race', value, 0)
+ for target, value in [(server, b'first'), (second_writer, b'second')]]
+ statuses = [task.result()[0] for task in tasks]
+ assert statuses.count(200) == 1 and all(status in [200, 412, 503] for status in statuses)
+ status, headers, body = rpc(server, 'GET', 'race')
+ assert status == 200 and headers['ETag'] == '"1"' and body in [b'first', b'second']
+ records.append(second_writer.stats)
+ checks.append('two native writers cannot both create the same expected revision')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'incomplete', 100, b'If-None-Match: *\r\n') + b'partial')
+ sock.shutdown(socket.SHUT_WR)
+ assert sock.recv(1) == b''
+ sock.close()
+ assert rpc(server, 'GET', 'incomplete')[0] == 404
+ checks.append('incomplete request never commits and releases its allocation')
+
+ # Force genuine partial socket sends. A write on another connection must
+ # not alter the immutable file whose bytes are still being transmitted.
+ large = bytes(range(256)) * 4096
+ assert rpc(server, 'PUT', 'large', large, 0)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.getheader('ETag') == '"1"'
+ assert response.read(17) == large[:17]
+ assert rpc(server, 'PUT', 'large', b'changed', 1)[0] == 200
+ assert response.read() == large[17:]
+ sock.close()
+ assert rpc(server, 'GET', 'large')[2] == b'changed'
+ checks.append('borrowed read remains the same snapshot during another commit')
+
+ assert rpc(server, 'PUT', 'large', large, 2)[0] == 200
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ assert sock.recv(1)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ sock.close()
+ assert rpc(server, 'GET', 'binary')[2] == b'new'
+ checks.append('receiver reset aborts an outstanding borrowed transfer')
+
+ assert wire(server, header('PUT', 'too_large', OBJECT_LIMIT + 1, b'If-None-Match: *\r\n'))[0] == 413
+ malformed = [
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nContent-Length: 1\r\nContent-Length: 1\r\nIf-None-Match: *\r\n\r\nx',
+ b'PUT /objects/bad HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n',
+ b'GET /objects/bad HTTP/1.1\r\nHost: x\x00hidden\r\n\r\n',
+ ]
+ for request in malformed:
+ assert wire(server, request)[0] == 400
+ assert rpc(server, 'GET', 'bad')[0] == 404
+ checks.append('unsupported framing and oversized payload are rejected before effects')
+
+ # Existing authoring path: define, manipulate, save remotely, reconstruct
+ # in a fresh runtime. No fabricated project fixture or mock storage.
+ source = WORKBENCH / 'examples' / 'direct.pure'
+ saved = directory / 'restored.json'
+ lines, _ = cli(server, 'point drag down 80 180\npoint drag move 210 210\npoint drag up 210 210\n'
+ 'connect $URL authored\npush 0\nquit\n', source)
+ snapshots = [line for line in lines if 'states' in line]
+ assert snapshots
+ expected_states = snapshots[-1]['states']
+ assert expected_states['x'] == 210 and expected_states['y'] == 190 and expected_states['dragging'] == 0
+ lines, _ = cli(server, f'connect $URL authored\npull\nsave-project {saved}\nquit\n')
+ assert [line for line in lines if 'states' in line][-1]['states'] == expected_states
+ document = json.loads(saved.read_text())
+ assert document['version'] == 2 and document['source'] == source.read_text()
+ lines, error = cli(server, 'connect $URL authored\npush 0\nquit\n', source, 1)
+ assert '412' in error
+ checks.append('existing workbench manipulation restores in a fresh runtime and reports conflict')
+
+ assert rpc(server, 'PUT', 'invalid_project', b'{"format":"pure-workbench","version":2,"source":"state x=1","states":[]}', 0)[0] == 200
+ lines, error = cli(server, 'show\nconnect $URL invalid_project\npull\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and error
+ lines, error = cli(server, 'point drag down 90 170\nconnect $URL authored\npull\npush\nshow\nquit\n', source, 1)
+ states = [line['states'] for line in lines if 'states' in line]
+ assert states[0] == states[-1] and states[-1]['dragging'] == 1
+ assert len(error.strip().splitlines()) == 2
+ checks.append('invalid or non-idle restore preserves local state and does not adopt remote revision')
+
+ assert rpc(server, 'PUT', 'wide_revision', rpc_bytes(saved), 0)[0] == 200
+ wide = storage / 'obj-wide_revision'
+ raw = wide.read_bytes()
+ wide.write_bytes(raw[:8] + struct.pack('<Q', 9007199254740993) + raw[16:])
+ lines, _ = cli(server, 'connect $URL wide_revision\npull\npush\nquit\n')
+ revisions = [line['revision'] for line in lines if 'remote' in line and 'revision' in line]
+ assert revisions == ['9007199254740993', '9007199254740994']
+ checks.append('revision above JavaScript safe integer round trips without numeric coercion')
+
+ sock = socket.create_connection(('127.0.0.1', server.port), timeout=8)
+ sock.sendall(header('PUT', 'unread_ack', 4, b'If-None-Match: *\r\n') + b'done')
+ try:
+ deadline = time.monotonic() + 3
+ while True:
+ committed = storage / 'obj-unread_ack'
+ if committed.exists():
+ assert committed.read_bytes()[24:] == b'done'
+ break
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ finally:
+ sock.close() # Client never consumes the successful response.
+ assert rpc(server, 'PUT', 'unread_ack', b'again', 0)[0] == 412
+ assert rpc(server, 'GET', 'unread_ack')[2] == b'done'
+ checks.append('unread acknowledgment does not undo commit or permit a stale retry')
+
+ # A disconnect after commit can hide the ACK; retries remain conditional.
+ assert rpc(server, 'PUT', 'empty', b'', 0)[0] == 200
+ assert rpc(server, 'GET', 'empty')[2] == b''
+ checks.append('empty body has a valid lifetime and stored revision')
+ records.append(server.stats)
+
+ with serving(binary, storage) as restarted:
+ assert rpc(restarted, 'GET', 'binary')[2] == b'new'
+ assert rpc(restarted, 'GET', 'authored')[2] == rpc_bytes(saved)
+ checks.append('committed authoring state survives process restart')
+ records.append(restarted.stats)
+
+ # Fixed small payload budget is an admission test, not a throughput workload.
+ with serving(binary, storage, budget=1024 * 1024, timeout=1200) as limited:
+ sock = socket.create_connection(('127.0.0.1', limited.port), timeout=8)
+ sock.sendall(header('GET', 'large'))
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200
+ assert response.read(1) == large[:1]
+ status, headers, _ = rpc(limited, 'GET', 'large')
+ assert status == 503 and headers['X-Pure-Error'] == 'payload_budget'
+ # Leave the first receiver stalled until the absolute connection deadline.
+ time.sleep(1.4)
+ assert rpc(limited, 'GET', 'binary')[2] == b'new'
+ response.close()
+ sock.close()
+ checks.append('slow consumer retains its lease; budget rejects another; deadline releases it')
+
+ idle = [socket.create_connection(('127.0.0.1', limited.port), timeout=8) for _ in range(8)]
+ try:
+ for s in idle:
+ s.sendall(b'G')
+ for s in idle:
+ assert s.recv(1) == b''
+ finally:
+ for s in idle:
+ s.close()
+ assert rpc(limited, 'GET', 'binary')[0] == 200
+ checks.append('connection slots stay bounded and recover after header deadlines')
+ assert limited.stats['budget_rejections'] >= 1 and limited.stats['expired'] >= 9
+ records.append(limited.stats)
+ prepared = authored_connections(binary, directory, storage, records, checks)
+ return {'kind': 'prepared-connection-correctness-not-performance', 'checks': checks,
+ 'prepared_connections': prepared,
+ 'server_runs': records, 'storage': server.ready['storage']}
+
+
+def authored_connections(binary, directory, storage, records, checks):
+ get = 'on get { let o = store.read(request.key); reply(o, o.body); }'
+ put = 'on put { let s = store.write(request.key, request.revision, request.body); reply(s); }'
+
+ def author(name, source):
+ path = directory / name
+ path.write_text(source)
+ return path
+
+ def explain(path):
+ return json.loads(subprocess.check_output([str(binary), '--check-program', str(path)], text=True))
+
+ with serving(binary, storage) as writer:
+ assert rpc(writer, 'PUT', 'short_parent', bytes(range(48)), 0)[0] == 200
+ assert rpc(writer, 'PUT', 'short_unused', bytes(range(80)), 0)[0] == 200
+ records.append(writer.stats)
+ excerpt = ROOT / 'examples/excerpt.pure'
+ prepared = {'excerpt': explain(excerpt)}
+ assert prepared['excerpt']['read'] == {
+ 'whole': False, 'offset': 32, 'length': 16, 'minimum_source_bytes': 80}
+ with serving(binary, storage, budget=16, program=excerpt) as selected:
+ status, headers, body = rpc(selected, 'GET', 'large')
+ assert status == 200 and body == bytes(range(32, 48)) and headers['ETag'] == '"3"'
+ # Final [32,48) fits, but the authored parent [16,80) does not.
+ assert rpc(selected, 'GET', 'short_parent')[0] == 413
+ assert rpc(selected, 'GET', 'missing')[0] == 404
+ assert selected.stats['peak_retained_payload_bytes'] == 16
+ records.append(selected.stats)
+ checks.append('authored nested read maps only final demand while preserving parent bounds and revision')
+
+ unused = author('unused.pure', 'on get { let o = store.read(request.key); '
+ 'let unused = range(o.body, 0, 96); let body = range(o.body, 32, 16); reply(o, body); } ' + put)
+ with serving(binary, storage, budget=16, program=unused) as guarded:
+ assert rpc(guarded, 'GET', 'short_unused')[0] == 413
+ assert rpc(guarded, 'GET', 'large')[2] == bytes(range(32, 48))
+ records.append(guarded.stats)
+ checks.append('unused checked view still fails even when response range would be valid')
+
+ select_write = author('write.pure', get + ' on put { let a = range(request.body, 2, 10); '
+ 'let b = range(a, 3, 4); let alias = b; '
+ 'let saved = store.write(request.key, request.revision, alias); reply(saved, b); }')
+ prepared['write'] = explain(select_write)
+ with serving(binary, storage, program=select_write) as writer:
+ status, headers, body = rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'GET', 'selected')[2] == b'5678'
+ assert rpc(writer, 'PUT', 'selected', b'012345678', 1)[0] == 413
+ status, headers, body = rpc(writer, 'GET', 'selected')
+ assert status == 200 and body == b'5678' and headers['ETag'] == '"1"'
+ assert rpc(writer, 'PUT', 'selected', b'0123456789AB', 0)[0] == 412
+ records.append(writer.stats)
+ checks.append('authored write and reply share selected input; invalid parent prevents the storage effect')
+
+ metadata = author('metadata.pure', 'on get { let o = store.read(request.key); reply(o); } ' + put)
+ with serving(binary, storage, budget=1, program=metadata) as meta:
+ status, headers, body = rpc(meta, 'GET', 'large')
+ assert status == 200 and headers['ETag'] == '"3"' and body == b''
+ assert rpc(meta, 'GET', 'absent')[0] == 404
+ assert rpc(meta, 'GET', 'broken')[0] == 500
+ assert meta.stats['peak_retained_payload_bytes'] == 0
+ records.append(meta.stats)
+ checks.append('body-free response preserves read existence and malformed-object errors')
+
+ echo = author('echo.pure', get + ' on put { let body = request.body; '
+ 'let saved = store.write(request.key, request.revision, body); reply(saved, body); }')
+ payload = bytes(range(256)) * 4096
+ with serving(binary, storage, budget=len(payload), program=echo) as echoed:
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo', len(payload), b'If-None-Match: *\r\n') + payload)
+ response = http.client.HTTPResponse(sock)
+ response.begin()
+ assert response.status == 200 and response.read(1) == payload[:1]
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ assert response.read() == payload[1:]
+ response.close()
+ assert rpc(echoed, 'GET', 'binary')[2] == b'new'
+ with socket.create_connection(('127.0.0.1', echoed.port), timeout=8) as sock:
+ sock.sendall(header('PUT', 'echo_abort', len(payload), b'If-None-Match: *\r\n') + payload)
+ assert sock.recv(1)
+ assert rpc(echoed, 'GET', 'binary')[0] == 503
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
+ deadline = time.monotonic() + 3
+ while rpc(echoed, 'GET', 'binary')[0] == 503:
+ assert time.monotonic() < deadline
+ time.sleep(0.01)
+ assert rpc(echoed, 'GET', 'echo_abort')[2] == payload
+ records.append(echoed.stats)
+ checks.append('input-backed response survives partial send and releases on finish or abort without undoing commit')
+
+ bad = author('invalid.pure', get + get + put)
+ untouched = directory / 'must_not_exist'
+ rejected = subprocess.run([str(binary), '--program', str(bad), '--store', str(untouched)],
+ capture_output=True, text=True, timeout=10)
+ assert rejected.returncode == 2 and 'duplicate handler' in rejected.stderr and not untouched.exists()
+ checks.append('invalid authored program fails preparation before creating storage or accepting requests')
+ return prepared
+
+
+def rpc_bytes(path):
+ # CLI export is pretty JSON; wire export is compact JSON with the same model.
+ return json.dumps(json.loads(path.read_text()), ensure_ascii=False, separators=(',', ':')).encode()
+
+
+def main():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('--server', type=Path, default=ROOT / 'build/pure-connections')
+ parser.add_argument('--output', type=Path)
+ args = parser.parse_args()
+ if args.output and args.output.exists():
+ parser.error('evidence file already exists')
+ binary = args.server.resolve()
+ with tempfile.TemporaryDirectory(prefix='pure-connections-check-') as temporary:
+ result = check(binary, Path(temporary))
+ result['binary_sha256'] = hashlib.sha256(binary.read_bytes()).hexdigest()
+ result['environment'] = {'platform': platform.platform(), 'machine': platform.machine(),
+ 'python': platform.python_version(), 'node': subprocess.check_output(['node', '--version'], text=True).strip()}
+ result['source_sha256'] = {str(path.relative_to(ROOT.parent.parent)): hashlib.sha256(path.read_bytes()).hexdigest()
+ for path in [*(ROOT / name for name in ('flow.c', 'flow.h', 'store.c', 'store.h', 'program.c', 'program.h',
+ 'server.c', 'check.py', 'test-flow.c', 'test-program.c', 'Makefile', 'examples/storage.pure', 'examples/excerpt.pure')),
+ *(WORKBENCH / name for name in ('remote.mjs', 'cli.mjs', 'web/core.wasm', 'web/runtime.mjs',
+ 'web/compiler.mjs', 'web/project.mjs', 'examples/direct.pure'))]}
+ output = json.dumps(result, ensure_ascii=False, indent=2) + '\n'
+ if args.output:
+ args.output.parent.mkdir(parents=True, exist_ok=True)
+ with args.output.open('x') as destination:
+ destination.write(output)
+ print(output, end='')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/examples/excerpt.pure b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/examples/excerpt.pure
new file mode 100644
index 0000000..622f9bb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/examples/excerpt.pure
@@ -0,0 +1,13 @@
+// Read bytes 32..47 of an object that must contain the complete 64-byte window.
+// Preparation keeps the size check for 16..79, and maps only 32..47 for reply.
+on get {
+ let object = store.read(request.key);
+ let window = range(object.body, 16, 64);
+ let excerpt = range(window, 16, 16);
+ reply(object, excerpt);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/examples/storage.pure b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/examples/storage.pure
new file mode 100644
index 0000000..ff54ea3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/examples/storage.pure
@@ -0,0 +1,11 @@
+// The host supplies request bytes, an object name, and the expected revision.
+// Failed storage results propagate to the host's response without executing reply.
+on get {
+ let object = store.read(request.key);
+ reply(object, object.body);
+}
+
+on put {
+ let saved = store.write(request.key, request.revision, request.body);
+ reply(saved);
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/flow.c b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/flow.c
new file mode 100644
index 0000000..1070c70
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/flow.c
@@ -0,0 +1,41 @@
+#include "flow.h"
+#include <assert.h>
+
+void pure_transfer_abort(PureTransfer *t) {
+ if (!t->active) return;
+ PureRelease release = t->release;
+ void *owner = t->owner;
+ *t = (PureTransfer){0};
+ if (release) release(owner);
+}
+
+static void advance(PureTransfer *t) {
+ while (t->active && t->part < 2 && t->offset == t->spans[t->part].size) {
+ t->part++;
+ t->offset = 0;
+ }
+ if (t->active && t->part == 2) pure_transfer_abort(t);
+}
+
+void pure_transfer_init(PureTransfer *t, PureSpan header, PureSpan body,
+ void *owner, PureRelease release) {
+ assert(!t->active);
+ assert((!header.size || header.data) && (!body.size || body.data));
+ *t = (PureTransfer){.spans = {header, body}, .owner = owner,
+ .release = release, .active = true};
+ advance(t);
+}
+
+PureSpan pure_transfer_next(const PureTransfer *t, size_t limit) {
+ if (!t->active) return (PureSpan){0};
+ PureSpan span = t->spans[t->part];
+ size_t remaining = span.size - t->offset;
+ return (PureSpan){span.data + t->offset, remaining < limit ? remaining : limit};
+}
+
+bool pure_transfer_consume(PureTransfer *t, size_t bytes) {
+ if (!t->active || bytes > t->spans[t->part].size - t->offset) return false;
+ t->offset += bytes;
+ advance(t);
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/flow.h b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/flow.h
new file mode 100644
index 0000000..6e27c58
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/flow.h
@@ -0,0 +1,25 @@
+#ifndef PURE_FLOW_H
+#define PURE_FLOW_H
+#include <stdbool.h>
+#include <stddef.h>
+
+typedef struct { const unsigned char *data; size_t size; } PureSpan;
+typedef void (*PureRelease)(void *owner);
+
+/* A borrowed body stays alive until every byte is consumed or the transfer is
+ * aborted. A successful send() consumes bytes; peer receipt is a separate fact.
+ * Single owner thread; callbacks must not reenter or reuse this transfer. */
+typedef struct {
+ PureSpan spans[2];
+ size_t part, offset;
+ void *owner;
+ PureRelease release;
+ bool active;
+} PureTransfer;
+
+void pure_transfer_init(PureTransfer *, PureSpan header, PureSpan body,
+ void *owner, PureRelease);
+PureSpan pure_transfer_next(const PureTransfer *, size_t limit);
+bool pure_transfer_consume(PureTransfer *, size_t bytes);
+void pure_transfer_abort(PureTransfer *);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/program.c b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/program.c
new file mode 100644
index 0000000..79101db
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/program.c
@@ -0,0 +1,233 @@
+#include "program.h"
+#include "store.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+enum { NAME = 256, NUMBER, SYMBOLS = 32 };
+typedef struct {
+ char name[32];
+ bool result;
+ PureRegion region;
+} Symbol;
+typedef struct {
+ const char *source;
+ size_t length, at, line, token_line;
+ int token;
+ char name[32];
+ size_t number;
+ char *error;
+ size_t error_size;
+ bool failed, put, effect;
+ Symbol symbols[SYMBOLS];
+ size_t count;
+ PureProgram program;
+} Parser;
+
+static bool reject(Parser *p, const char *message) {
+ if (!p->failed && p->error_size) snprintf(p->error, p->error_size, "line %zu: %s", p->token_line, message);
+ p->failed = true;
+ return false;
+}
+
+static bool letter(char c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
+}
+
+static bool next(Parser *p) {
+ while (p->at < p->length) {
+ char c = p->source[p->at];
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ if (c == '\n') ++p->line;
+ ++p->at;
+ } else if (c == '/' && p->at + 1 < p->length && p->source[p->at + 1] == '/') {
+ while (p->at < p->length && p->source[p->at] != '\n') ++p->at;
+ } else break;
+ }
+ p->token_line = p->line;
+ p->name[0] = 0;
+ p->token = 0;
+ if (p->at == p->length) return true;
+ char c = p->source[p->at++];
+ if (letter(c)) {
+ size_t start = p->at - 1;
+ while (p->at < p->length && (letter(p->source[p->at]) ||
+ (p->source[p->at] >= '0' && p->source[p->at] <= '9'))) ++p->at;
+ size_t size = p->at - start;
+ if (size >= sizeof(p->name)) return reject(p, "name exceeds 31 bytes");
+ memcpy(p->name, p->source + start, size);
+ p->name[size] = 0;
+ p->token = NAME;
+ } else if (c >= '0' && c <= '9') {
+ size_t value = (size_t)(c - '0');
+ while (p->at < p->length && p->source[p->at] >= '0' && p->source[p->at] <= '9') {
+ unsigned digit = (unsigned)(p->source[p->at++] - '0');
+ if (value > (SIZE_MAX - digit) / 10) return reject(p, "integer overflow");
+ value = value * 10 + digit;
+ }
+ p->number = value;
+ p->token = NUMBER;
+ } else if (c && strchr("{}().,=;", c)) p->token = (unsigned char)c;
+ else return reject(p, "unexpected character");
+ return true;
+}
+
+static bool is_word(Parser *p, const char *word) {
+ return p->token == NAME && !strcmp(p->name, word);
+}
+
+static bool word(Parser *p, const char *expected) {
+ return is_word(p, expected) ? next(p) : reject(p, expected);
+}
+
+static bool token(Parser *p, int expected) {
+ return p->token == expected ? next(p) : reject(p, "unexpected token");
+}
+
+static Symbol *find(Parser *p, const char *name) {
+ for (size_t i = 0; i < p->count; ++i)
+ if (!strcmp(name, p->symbols[i].name)) return &p->symbols[i];
+ return NULL;
+}
+
+static bool field(Parser *p, const char *object, const char *name) {
+ return word(p, object) && token(p, '.') && word(p, name);
+}
+
+static bool reference(Parser *p, PureRegion *out) {
+ if (is_word(p, "request")) {
+ if (!p->put) return reject(p, "request.body is only available in on put");
+ *out = (PureRegion){.whole = true};
+ return field(p, "request", "body");
+ }
+ Symbol *s = p->token == NAME ? find(p, p->name) : NULL;
+ if (!s) return reject(p, "unknown byte source");
+ bool result = s->result;
+ *out = s->region;
+ if (!next(p)) return false;
+ if (!result) return true;
+ if (p->put) return reject(p, "write result has no body; use the input value");
+ *out = (PureRegion){.whole = true};
+ return token(p, '.') && word(p, "body");
+}
+
+static bool view(Parser *p, PureRegion *out) {
+ if (!is_word(p, "range")) return reference(p, out);
+ PureRegion parent;
+ size_t offset, length;
+ if (!next(p) || !token(p, '(') || !reference(p, &parent) || !token(p, ',')) return false;
+ if (p->token != NUMBER) return reject(p, "range offset must be a constant integer");
+ offset = p->number;
+ if (!next(p) || !token(p, ',')) return false;
+ if (p->token != NUMBER) return reject(p, "range length must be a constant integer");
+ length = p->number;
+ if (!next(p) || !token(p, ')')) return false;
+ size_t bound = parent.whole ? PURE_OBJECT_LIMIT : parent.length;
+ if (offset > bound || length > bound - offset) return reject(p, "range exceeds its source bound");
+ *out = (PureRegion){.offset = parent.offset + offset, .length = length};
+ size_t required = out->offset + out->length;
+ size_t *minimum = p->put ? &p->program.input_required : &p->program.read_required;
+ if (required > *minimum) *minimum = required;
+ ++p->program.range_definitions;
+ return true;
+}
+
+static bool effect(Parser *p, Symbol *out) {
+ if (p->effect) return reject(p, "only one storage effect is supported per handler");
+ if (!word(p, "store") || !token(p, '.') || !word(p, p->put ? "write" : "read") ||
+ !token(p, '(') || !field(p, "request", "key")) return false;
+ if (p->put) {
+ if (!token(p, ',') || !field(p, "request", "revision") || !token(p, ',') ||
+ !reference(p, &p->program.write)) return false;
+ }
+ if (!token(p, ')')) return false;
+ out->result = true;
+ p->effect = true;
+ return true;
+}
+
+static bool handler(Parser *p) {
+ p->count = 0;
+ p->effect = false;
+ if (!token(p, '{')) return false;
+ while (is_word(p, "let")) {
+ if (p->put && p->effect) return reject(p, "all views must precede store.write; reply must follow it");
+ if (p->count == SYMBOLS) return reject(p, "handler exceeds 32 definitions");
+ if (!next(p)) return false;
+ if (p->token != NAME || is_word(p, "request") || is_word(p, "store") || is_word(p, "range"))
+ return reject(p, "expected a non-reserved definition name");
+ if (find(p, p->name)) return reject(p, "duplicate definition");
+ Symbol symbol = {0};
+ strcpy(symbol.name, p->name);
+ if (!next(p) || !token(p, '=')) return false;
+ if (is_word(p, "store")) {
+ if (!effect(p, &symbol)) return false;
+ } else {
+ if (!view(p, &symbol.region)) return false;
+ ++p->program.view_definitions;
+ }
+ if (!token(p, ';')) return false;
+ p->symbols[p->count++] = symbol;
+ }
+ if (!p->effect) return reject(p, "handler requires its storage effect");
+ if (!word(p, "reply") || !token(p, '(')) return false;
+ Symbol *result = p->token == NAME ? find(p, p->name) : NULL;
+ if (!result || !result->result) return reject(p, "reply requires this handler's storage result");
+ if (!next(p)) return false;
+ PureRegion body = {0};
+ bool has_body = p->token == ',';
+ if (has_body && (!next(p) || !reference(p, &body))) return false;
+ if (!token(p, ')') || !token(p, ';') || !token(p, '}')) return false;
+ if (p->put) {
+ p->program.reply = body;
+ p->program.reply_input = has_body;
+ } else p->program.read = body;
+ return true;
+}
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size) {
+ Parser p = {.source = source, .length = length, .line = 1, .token_line = 1,
+ .error = error, .error_size = error_size};
+ if (error_size) error[0] = 0;
+ if (length > PURE_PROGRAM_LIMIT) return reject(&p, "program exceeds 16 KiB");
+ if (!next(&p)) return false;
+ unsigned handlers = 0;
+ while (p.token) {
+ if (!word(&p, "on")) return false;
+ if (!is_word(&p, "get") && !is_word(&p, "put")) return reject(&p, "expected get or put handler");
+ p.put = is_word(&p, "put");
+ unsigned bit = p.put ? 2 : 1;
+ if (handlers & bit) return reject(&p, "duplicate handler");
+ handlers |= bit;
+ if (!next(&p) || !handler(&p)) return false;
+ }
+ if (handlers != 3) return reject(&p, "both get and put handlers are required");
+ *out = p.program; /* Invalid preparation never changes the installed plan. */
+ return true;
+}
+
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size) {
+ FILE *file = fopen(path, "rb");
+ if (!file) {
+ if (error_size) snprintf(error, error_size, "cannot open program");
+ return false;
+ }
+ char source[PURE_PROGRAM_LIMIT + 1];
+ size_t length = fread(source, 1, sizeof(source), file);
+ bool bad = ferror(file) != 0;
+ if (fclose(file)) bad = true;
+ if (bad) {
+ if (error_size) snprintf(error, error_size, "cannot read program");
+ return false;
+ }
+ return pure_program_parse(source, length, out, error, error_size);
+}
+
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out) {
+ *out = (PureSpan){0};
+ if (region.whole) { *out = source; return true; }
+ if (region.offset > source.size || region.length > source.size - region.offset) return false;
+ *out = (PureSpan){region.length ? source.data + region.offset : NULL, region.length};
+ return true;
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/program.h b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/program.h
new file mode 100644
index 0000000..29764db
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/program.h
@@ -0,0 +1,26 @@
+#ifndef PURE_PROGRAM_H
+#define PURE_PROGRAM_H
+#include "flow.h"
+
+#define PURE_PROGRAM_LIMIT 16384u
+typedef struct {
+ size_t offset, length;
+ bool whole;
+} PureRegion;
+
+/* Prepared connections, not an instruction stream. All view definitions are
+ * checked at preparation; their root-length requirements survive elimination.
+ * Input views are evaluated before the write effect. A read still opens and
+ * validates the object even if its response has no body. */
+typedef struct {
+ PureRegion read, write, reply;
+ size_t read_required, input_required;
+ size_t view_definitions, range_definitions;
+ bool reply_input;
+} PureProgram;
+
+bool pure_program_parse(const char *source, size_t length, PureProgram *out,
+ char *error, size_t error_size);
+bool pure_program_load(const char *path, PureProgram *out, char *error, size_t error_size);
+bool pure_region_span(PureRegion region, PureSpan source, PureSpan *out);
+#endif
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/server.c b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/server.c
new file mode 100644
index 0000000..3822c66
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/server.c
@@ -0,0 +1,385 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include "program.h"
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+enum { SLOTS = 8, HEADER_LIMIT = 4096, CHUNK = 65536 };
+typedef enum { READING_HEADER, READING_BODY, WRITING } Phase;
+typedef struct Server Server;
+typedef struct {
+ int fd;
+ Phase phase;
+ uint64_t deadline;
+ char request[HEADER_LIMIT + 1], response[512], key[65];
+ size_t header_size, body_size, received, charged;
+ unsigned char *body;
+ bool put;
+ int64_t expected;
+ PureStoredView stored;
+ PureTransfer transfer;
+ Server *server;
+} Connection;
+struct Server {
+ const char *path;
+ PureProgram program;
+ size_t budget, retained, peak_retained, active, peak_active;
+ uint64_t accepted, commits, gets, conflicts, budget_rejections, expired;
+ uint64_t releases, prefix_copy_bytes, borrowed_output_bytes;
+ uint64_t timeout_ms;
+ int send_buffer;
+ Connection connections[SLOTS];
+};
+static volatile sig_atomic_t stopping;
+static void stop_server(int sig) { (void)sig; stopping = 1; }
+
+static uint64_t now_ms(void) {
+ struct timespec t;
+ if (clock_gettime(CLOCK_MONOTONIC, &t)) abort();
+ return (uint64_t)t.tv_sec * 1000 + (uint64_t)t.tv_nsec / 1000000;
+}
+
+static bool number(const char *text, uint64_t maximum, uint64_t *value) {
+ if (!*text) return false;
+ uint64_t n = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > maximum || n > (maximum - digit) / 10) return false;
+ n = n * 10 + digit;
+ }
+ *value = n;
+ return true;
+}
+
+static void release_payload(void *owner) {
+ Connection *c = owner;
+ bool owned = c->body || c->stored.mapped_size || c->charged;
+ pure_store_release(&c->stored);
+ free(c->body);
+ c->body = NULL;
+ assert(c->charged <= c->server->retained);
+ c->server->retained -= c->charged;
+ c->charged = 0;
+ if (owned) ++c->server->releases;
+}
+
+static void close_connection(Connection *c) {
+ if (c->fd < 0) return;
+ if (c->transfer.active) pure_transfer_abort(&c->transfer);
+ else if (c->body || c->stored.mapped_size || c->charged) release_payload(c);
+ close(c->fd);
+ --c->server->active;
+ *c = (Connection){.fd = -1};
+}
+
+static bool charge(Connection *c, size_t size) {
+ Server *s = c->server;
+ if (size > s->budget - s->retained) { ++s->budget_rejections; return false; }
+ s->retained += size;
+ c->charged += size;
+ if (s->retained > s->peak_retained) s->peak_retained = s->retained;
+ return true;
+}
+
+static void respond(Connection *c, int status, const char *reason, const char *error,
+ int64_t revision, PureSpan body) {
+ char tag[80] = "";
+ if (revision > 0) snprintf(tag, sizeof(tag), "ETag: \"%" PRId64 "\"\r\n", revision);
+ int length = snprintf(c->response, sizeof(c->response),
+ "HTTP/1.1 %d %s\r\nContent-Length: %zu\r\nConnection: close\r\n"
+ "Content-Type: application/octet-stream\r\nCache-Control: no-store\r\n"
+ "X-Pure-Error: %s\r\n%s\r\n", status, reason, body.size, error, tag);
+ assert(length > 0 && (size_t)length < sizeof(c->response));
+ c->phase = WRITING;
+ pure_transfer_init(&c->transfer,
+ (PureSpan){(const unsigned char *)c->response, (size_t)length}, body, c, release_payload);
+}
+
+static void fail(Connection *c, int status, const char *reason, const char *error) {
+ /* No outstanding backend access on the owner thread at this point. */
+ if (c->body || c->stored.mapped_size || c->charged) release_payload(c);
+ respond(c, status, reason, error, 0, (PureSpan){0});
+}
+
+static void run_request(Connection *c) {
+ PureResult result;
+ int64_t revision = 0;
+ PureProgram *program = &c->server->program;
+ PureSpan output = {0};
+ if (c->put) {
+ PureSpan source = {c->body, c->body_size}, value;
+ /* Validate every authored view before performing an external effect,
+ * including unused views. Static preparation preserves these guards. */
+ if (source.size < program->input_required ||
+ !pure_region_span(program->write, source, &value) ||
+ (program->reply_input && !pure_region_span(program->reply, source, &output))) {
+ fail(c, 413, "Content Too Large", "limit");
+ return;
+ }
+ result = pure_store_put(c->server->path, c->key, c->expected, value, &revision);
+ /* A reply can consume the same input. Its owner lives until transfer
+ * completion; otherwise storage completion ends the input lifetime. */
+ if (result != PURE_OK || !output.size) { release_payload(c); output = (PureSpan){0}; }
+ if (result == PURE_OK) {
+ ++c->server->commits;
+ c->server->borrowed_output_bytes += output.size;
+ }
+ } else {
+ result = pure_store_select(c->server->path, c->key, program->read.offset,
+ program->read.length, program->read.whole, program->read_required,
+ c->server->budget - c->server->retained, &c->stored);
+ if (result == PURE_OK) {
+ if (!charge(c, c->stored.body.size)) abort(); /* Same owner thread. */
+ revision = c->stored.revision;
+ output = c->stored.body;
+ ++c->server->gets;
+ c->server->borrowed_output_bytes += c->stored.body.size;
+ } else if (result == PURE_BUDGET) ++c->server->budget_rejections;
+ }
+ switch (result) {
+ case PURE_OK: respond(c, 200, "OK", "none", revision, output); break;
+ case PURE_NOT_FOUND: fail(c, 404, "Not Found", "not_found"); break;
+ case PURE_CONFLICT:
+ ++c->server->conflicts;
+ respond(c, 412, "Precondition Failed", "conflict", revision, (PureSpan){0}); break;
+ case PURE_BUSY: fail(c, 503, "Service Unavailable", "store_busy"); break;
+ case PURE_BUDGET: fail(c, 503, "Service Unavailable", "payload_budget"); break;
+ case PURE_LIMIT: fail(c, 413, "Content Too Large", "limit"); break;
+ case PURE_UNCERTAIN: fail(c, 500, "Internal Server Error", "durability_unknown"); break;
+ default: fail(c, 500, "Internal Server Error", "storage"); break;
+ }
+}
+
+/* Deliberately bounded HTTP/1.1 subset: one GET/PUT, Content-Length, close.
+ * No transfer coding, pipelining, trailers, Expect, URL decoding, or proxying. */
+static bool parse_header(Connection *c, size_t end) {
+ for (size_t i = 0; i < end; ++i) {
+ unsigned char b = (unsigned char)c->request[i];
+ if ((b < 32 && b != '\r' && b != '\n' && b != '\t') || b == 127) return false;
+ }
+ char *line = c->request, *next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *path = strchr(line, ' ');
+ if (!path) return false;
+ *path++ = 0;
+ if (strcmp(line, "PUT") == 0) c->put = true;
+ else if (strcmp(line, "GET") != 0) return false;
+ char *version = strchr(path, ' ');
+ if (!version) return false;
+ *version++ = 0;
+ if (strcmp(version, "HTTP/1.1") || strncmp(path, "/objects/", 9)) return false;
+ const char *key = path + 9;
+ size_t key_size = strlen(key);
+ if (!key_size || key_size > 64) return false;
+ for (size_t i = 0; i < key_size; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ memcpy(c->key, key, key_size + 1);
+ bool length_seen = false, condition_seen = false, host_seen = false;
+ line = next + 2;
+ while (*line != '\r') {
+ next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *value = strchr(line, ':');
+ if (!value || value == line) return false;
+ *value++ = 0;
+ for (char *p = line; *p; ++p)
+ if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') || *p == '-')) return false;
+ while (*value == ' ' || *value == '\t') ++value;
+ char *tail = value + strlen(value);
+ while (tail > value && (tail[-1] == ' ' || tail[-1] == '\t')) *--tail = 0;
+ if (strchr(value, '\r') || strchr(value, '\n')) return false;
+ uint64_t n;
+ if (!strcasecmp(line, "Content-Length")) {
+ if (length_seen || !number(value, SIZE_MAX, &n)) return false;
+ length_seen = true;
+ c->body_size = (size_t)n;
+ } else if (!strcasecmp(line, "Host")) {
+ if (host_seen || !*value) return false;
+ host_seen = true;
+ } else if (!strcasecmp(line, "If-Match")) {
+ if (condition_seen || tail - value < 3 || *value != '"' || tail[-1] != '"') return false;
+ tail[-1] = 0;
+ if (!number(value + 1, INT64_MAX, &n) || !n) return false;
+ c->expected = (int64_t)n;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "If-None-Match")) {
+ if (condition_seen || strcmp(value, "*")) return false;
+ c->expected = 0;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "Transfer-Encoding") || !strcasecmp(line, "Expect")) return false;
+ line = next + 2;
+ }
+ return host_seen && (c->put ? length_seen && condition_seen : !condition_seen && c->body_size == 0);
+}
+
+static void read_connection(Connection *c) {
+ if (c->phase == READING_HEADER) {
+ ssize_t n = recv(c->fd, c->request + c->header_size, HEADER_LIMIT - c->header_size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->header_size += (size_t)n;
+ c->request[c->header_size] = 0;
+ /* Scan by byte count, so embedded NUL cannot hide a terminator. */
+ size_t end = 0;
+ for (size_t i = 3; i < c->header_size; ++i)
+ if (!memcmp(c->request + i - 3, "\r\n\r\n", 4)) { end = i + 1; break; }
+ if (!end) {
+ if (c->header_size == HEADER_LIMIT) fail(c, 431, "Request Header Fields Too Large", "headers");
+ return;
+ }
+ size_t prefix = c->header_size - end;
+ if (!parse_header(c, end)) { fail(c, 400, "Bad Request", "request"); return; }
+ if (c->body_size > PURE_OBJECT_LIMIT) { fail(c, 413, "Content Too Large", "limit"); return; }
+ if (prefix > c->body_size) { fail(c, 400, "Bad Request", "extra_body"); return; }
+ if (!c->put) { run_request(c); return; }
+ if (!charge(c, c->body_size)) { fail(c, 503, "Service Unavailable", "payload_budget"); return; }
+ c->body = malloc(c->body_size ? c->body_size : 1);
+ if (!c->body) { fail(c, 503, "Service Unavailable", "allocation"); return; }
+ if (prefix) memcpy(c->body, c->request + end, prefix);
+ c->server->prefix_copy_bytes += prefix;
+ c->received = prefix;
+ c->phase = READING_BODY;
+ if (c->received == c->body_size) run_request(c);
+ } else {
+ size_t remaining = c->body_size - c->received;
+ ssize_t n = recv(c->fd, c->body + c->received, remaining < CHUNK ? remaining : CHUNK, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->received += (size_t)n;
+ if (c->received == c->body_size) run_request(c);
+ }
+}
+
+static void write_connection(Connection *c) {
+ PureSpan span = pure_transfer_next(&c->transfer, CHUNK);
+ ssize_t n = send(c->fd, span.data, span.size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ if (!pure_transfer_consume(&c->transfer, (size_t)n)) abort();
+ if (!c->transfer.active) close_connection(c);
+}
+
+static bool nonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
+}
+
+int main(int argc, char **argv) {
+ Server server = {.budget = 4u * 1024u * 1024u, .timeout_ms = 10000};
+ unsigned port = 8767;
+ const char *program_path = NULL;
+ bool explain = argc == 3 && !strcmp(argv[1], "--check-program");
+ char program_error[160];
+ if (explain) program_path = argv[2];
+ for (int i = 1; !explain && i < argc; i += 2) {
+ if (i + 1 == argc) goto usage;
+ uint64_t value;
+ if (!strcmp(argv[i], "--store")) server.path = argv[i + 1];
+ else if (!strcmp(argv[i], "--program")) program_path = argv[i + 1];
+ else if (!strcmp(argv[i], "--port") && number(argv[i + 1], 65535, &value)) port = (unsigned)value;
+ else if (!strcmp(argv[i], "--budget") && number(argv[i + 1], SIZE_MAX, &value) && value) server.budget = (size_t)value;
+ else if (!strcmp(argv[i], "--timeout-ms") && number(argv[i + 1], 3600000, &value) && value) server.timeout_ms = value;
+ else if (!strcmp(argv[i], "--send-buffer") && number(argv[i + 1], INT32_MAX, &value)) server.send_buffer = (int)value;
+ else goto usage;
+ }
+ if (!program_path || (!explain && !server.path)) goto usage;
+ if (!pure_program_load(program_path, &server.program, program_error, sizeof(program_error))) {
+ fprintf(stderr, "Program: %s\n", program_error); return 2;
+ }
+ if (explain) {
+ PureProgram *p = &server.program;
+ printf("{\"read\":{\"whole\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"write\":{\"whole\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"reply_input\":%s,\"view_definitions\":%zu,\"range_definitions\":%zu,"
+ "\"runtime_view_steps\":0,\"prepared_program_bytes\":%zu}\n",
+ p->read.whole ? "true" : "false", p->read.offset, p->read.length, p->read_required,
+ p->write.whole ? "true" : "false", p->write.offset, p->write.length, p->input_required,
+ p->reply_input ? "true" : "false", p->view_definitions, p->range_definitions, sizeof(*p));
+ return 0;
+ }
+ if (pure_store_init(server.path) != PURE_OK) { fputs("Cannot initialize byte store directory\n", stderr); return 1; }
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGINT, stop_server);
+ signal(SIGTERM, stop_server);
+ int listener = socket(AF_INET, SOCK_STREAM, 0);
+ if (listener < 0) { perror("socket"); return 1; }
+ int one = 1;
+ setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ struct sockaddr_in address = {.sin_family = AF_INET, .sin_port = htons((uint16_t)port),
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ if (bind(listener, (struct sockaddr *)&address, sizeof(address)) || listen(listener, SLOTS) || !nonblocking(listener)) {
+ perror("listen"); close(listener); return 1;
+ }
+ socklen_t address_size = sizeof(address);
+ if (getsockname(listener, (struct sockaddr *)&address, &address_size)) { close(listener); return 1; }
+ for (size_t i = 0; i < SLOTS; ++i) server.connections[i].fd = -1;
+ printf("{\"port\":%u,\"storage\":\"immutable-byte-extents-v1\"}\n", ntohs(address.sin_port));
+ fflush(stdout);
+ while (!stopping) {
+ struct pollfd polls[SLOTS + 1] = {{.fd = server.active < SLOTS ? listener : -1, .events = POLLIN}};
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ polls[i + 1] = (struct pollfd){.fd = c->fd, .events = c->phase == WRITING ? POLLOUT : POLLIN};
+ }
+ int ready = poll(polls, SLOTS + 1, 50);
+ if (ready < 0 && errno != EINTR) { perror("poll"); stopping = 1; }
+ uint64_t now = now_ms();
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ if (c->fd < 0) continue;
+ if (now >= c->deadline) { ++server.expired; close_connection(c); continue; }
+ short events = polls[i + 1].revents;
+ if (events & (POLLERR | POLLNVAL)) { close_connection(c); continue; }
+ if (events & (POLLIN | POLLOUT | POLLHUP)) {
+ if (c->phase == WRITING) write_connection(c); else read_connection(c);
+ }
+ }
+ if (!stopping && (polls[0].revents & POLLIN)) {
+ int fd = accept(listener, NULL, NULL);
+ if (fd < 0) continue;
+ if (!nonblocking(fd)) { close(fd); continue; }
+ if (server.send_buffer) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &server.send_buffer, sizeof(server.send_buffer));
+ for (size_t i = 0; i < SLOTS; ++i) if (server.connections[i].fd < 0) {
+ server.connections[i] = (Connection){.fd = fd, .server = &server, .deadline = now_ms() + server.timeout_ms};
+ ++server.active;
+ ++server.accepted;
+ if (server.active > server.peak_active) server.peak_active = server.active;
+ break;
+ }
+ }
+ }
+ close(listener);
+ for (size_t i = 0; i < SLOTS; ++i) close_connection(&server.connections[i]);
+ fprintf(stderr, "{\"active\":%zu,\"retained_payload_bytes\":%zu,\"peak_retained_payload_bytes\":%zu,"
+ "\"payload_budget\":%zu,\"peak_connections\":%zu,\"accepted\":%" PRIu64 ",\"commits\":%" PRIu64 ","
+ "\"gets\":%" PRIu64 ",\"conflicts\":%" PRIu64 ",\"budget_rejections\":%" PRIu64 ","
+ "\"expired\":%" PRIu64 ",\"releases\":%" PRIu64 ",\"ingress_prefix_copy_bytes\":%" PRIu64 ","
+ "\"borrowed_output_bytes\":%" PRIu64 ",\"server_structure_bytes\":%zu}\n",
+ server.active, server.retained, server.peak_retained, server.budget, server.peak_active,
+ server.accepted, server.commits, server.gets, server.conflicts, server.budget_rejections,
+ server.expired, server.releases, server.prefix_copy_bytes, server.borrowed_output_bytes, sizeof(server));
+ return 0;
+usage:
+ fputs("pure-connections --program FILE --store DIRECTORY [--port 8767] [--budget BYTES] [--timeout-ms 10000] [--send-buffer BYTES]\n"
+ "pure-connections --check-program FILE\n", stderr);
+ return 2;
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/store.c b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/store.c
new file mode 100644
index 0000000..759f210
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/store.c
@@ -0,0 +1,227 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Immutable extent envelope: marker, little-endian u64 revision and payload
+ * length, then unchanged caller bytes. Single-threaded control API; cooperating
+ * processes serialize publication using .writer.lock. */
+enum { HEADER_BYTES = 24 };
+static const unsigned char magic[8] = {'P','U','R','E','B','0','0','1'};
+static uint64_t temporary_sequence;
+
+static bool fault(PureStoreStage stage) {
+#ifdef PURE_STORE_TEST
+ if (pure_store_test_fault(stage)) { errno = EIO; return true; }
+#else
+ (void)stage;
+#endif
+ return false;
+}
+
+static bool file_name(const char *key, char name[72]) {
+ if (!key) return false;
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ snprintf(name, 72, "obj-%s", key);
+ return true;
+}
+
+static uint64_t decode64(const unsigned char *bytes) {
+ uint64_t value = 0;
+ for (unsigned i = 0; i < 8; ++i) value |= (uint64_t)bytes[i] << (8 * i);
+ return value;
+}
+
+static void encode64(unsigned char *bytes, uint64_t value) {
+ for (unsigned i = 0; i < 8; ++i) bytes[i] = (unsigned char)(value >> (8 * i));
+}
+
+static bool sync_fd(int fd) {
+ int rc;
+ do { rc = fsync(fd); } while (rc && errno == EINTR);
+ return rc == 0;
+}
+
+static bool write_bytes(int fd, const unsigned char *bytes, size_t length) {
+ while (length) {
+ ssize_t n = write(fd, bytes, length);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ bytes += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static bool read_header(int fd, int64_t *revision, size_t *length) {
+ struct stat info;
+ if (fstat(fd, &info) || !S_ISREG(info.st_mode)) return false;
+ unsigned char header[HEADER_BYTES];
+ size_t used = 0;
+ while (used < sizeof(header)) {
+ ssize_t n = pread(fd, header + used, sizeof(header) - used, (off_t)used);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ used += (size_t)n;
+ }
+ uint64_t version = decode64(header + 8), size = decode64(header + 16);
+ if (memcmp(header, magic, sizeof(magic)) || !version || version > INT64_MAX ||
+ size > PURE_OBJECT_LIMIT || info.st_size != (off_t)(HEADER_BYTES + size)) return false;
+ *revision = (int64_t)version;
+ *length = (size_t)size;
+ return true;
+}
+
+PureResult pure_store_init(const char *path) {
+ if (!path || !*path) return PURE_STORE_ERROR;
+ bool created = mkdir(path, 0700) == 0;
+ if (!created && errno != EEXIST) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR; /* Never reinterpret an old DB file. */
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600);
+ struct stat info;
+ bool ok = lock >= 0 && fstat(lock, &info) == 0 && S_ISREG(info.st_mode) && sync_fd(lock);
+ if (lock >= 0) close(lock);
+ if (ok) ok = sync_fd(directory);
+ close(directory);
+ if (!ok) return PURE_STORE_ERROR;
+ if (created) {
+ char *parent = strdup(path);
+ if (!parent) return PURE_STORE_ERROR;
+ size_t length = strlen(parent);
+ while (length > 1 && parent[length - 1] == '/') parent[--length] = 0;
+ char *slash = strrchr(parent, '/');
+ if (!slash) strcpy(parent, ".");
+ else if (slash == parent) parent[1] = 0;
+ else *slash = 0;
+ int fd = open(parent, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ free(parent);
+ ok = fd >= 0 && sync_fd(fd);
+ if (fd >= 0) close(fd);
+ }
+ return ok ? PURE_OK : PURE_STORE_ERROR;
+}
+
+void pure_store_release(PureStoredView *view) {
+ if (view->mapped_size) munmap(view->mapping, view->mapped_size);
+ *view = (PureStoredView){0};
+}
+
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out) {
+ *out = (PureStoredView){0};
+ char name[72];
+ if (!file_name(key, name)) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ int cause = errno;
+ close(directory);
+ if (fd < 0) return cause == ENOENT ? PURE_NOT_FOUND : PURE_STORE_ERROR;
+ int64_t revision;
+ size_t size;
+ PureResult result = PURE_STORE_ERROR;
+ if (!read_header(fd, &revision, &size)) goto finish;
+ if (size < minimum) { result = PURE_LIMIT; goto finish; }
+ if (whole) { offset = 0; length = size; }
+ if (offset > size || length > size - offset) { result = PURE_LIMIT; goto finish; }
+ if (length > available) { result = PURE_BUDGET; goto finish; }
+ if (length) {
+ long page = sysconf(_SC_PAGESIZE);
+ if (page <= 0) goto finish;
+ size_t start = HEADER_BYTES + offset;
+ size_t aligned = start - start % (size_t)page;
+ size_t prefix = start - aligned;
+ size_t mapped_size = prefix + length;
+ void *mapping = mmap(NULL, mapped_size, PROT_READ, MAP_PRIVATE, fd, (off_t)aligned);
+ if (mapping == MAP_FAILED) goto finish;
+ out->mapping = mapping;
+ out->mapped_size = mapped_size;
+ out->body = (PureSpan){(const unsigned char *)mapping + prefix, length};
+ }
+ out->revision = revision;
+ out->object_size = size;
+ result = PURE_OK;
+finish:
+ close(fd); /* The mapping retains this immutable file version after rename. */
+ return result;
+}
+
+PureResult pure_store_get(const char *path, const char *key, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, 0, 0, true, 0, available, out);
+}
+
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, offset, length, false, 0, available, out);
+}
+
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ *revision = 0;
+ char name[72], temporary[96] = "";
+ if (!file_name(key, name) || (body.size && !body.data)) return PURE_STORE_ERROR;
+ if (body.size > PURE_OBJECT_LIMIT || expected < 0) return PURE_LIMIT;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_NOFOLLOW | O_CLOEXEC);
+ int fd = -1;
+ PureResult result = PURE_STORE_ERROR;
+ struct stat info;
+ if (lock < 0 || fstat(lock, &info) || !S_ISREG(info.st_mode)) goto finish;
+ struct flock hold = {.l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0};
+ if (fcntl(lock, F_SETLK, &hold)) {
+ if (errno == EACCES || errno == EAGAIN) result = PURE_BUSY;
+ goto finish;
+ }
+ fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (fd >= 0) {
+ size_t size;
+ if (!read_header(fd, revision, &size)) goto finish;
+ close(fd);
+ fd = -1;
+ } else if (errno != ENOENT) goto finish;
+ if (*revision != expected) { result = PURE_CONFLICT; goto finish; }
+ if (*revision == INT64_MAX) { result = PURE_LIMIT; goto finish; }
+ for (unsigned attempt = 0; attempt < 64; ++attempt) {
+ if (temporary_sequence == UINT64_MAX) goto finish;
+ snprintf(temporary, sizeof(temporary), ".pending-%ld-%" PRIu64, (long)getpid(), ++temporary_sequence);
+ fd = openat(directory, temporary, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
+ if (fd >= 0) break;
+ temporary[0] = 0; /* Never remove an existing file on a name collision. */
+ if (errno != EEXIST) goto finish;
+ }
+ if (fd < 0) goto finish;
+ unsigned char header[HEADER_BYTES];
+ memcpy(header, magic, sizeof(magic));
+ encode64(header + 8, (uint64_t)*revision + 1);
+ encode64(header + 16, body.size);
+ if (!write_bytes(fd, header, sizeof(header)) || fault(PURE_AFTER_HEADER) ||
+ !write_bytes(fd, body.data, body.size) || fault(PURE_BEFORE_FILE_SYNC) || !sync_fd(fd)) goto finish;
+ int close_result = close(fd);
+ fd = -1;
+ if (close_result || fault(PURE_BEFORE_RENAME) || renameat(directory, temporary, directory, name)) goto finish;
+ temporary[0] = 0; /* Published: a later sync failure does not roll it back. */
+ ++*revision;
+ result = fault(PURE_BEFORE_DIR_SYNC) || !sync_fd(directory) ? PURE_UNCERTAIN : PURE_OK;
+finish:
+ if (fd >= 0) close(fd);
+ if (*temporary) unlinkat(directory, temporary, 0);
+ if (lock >= 0) close(lock);
+ close(directory);
+ return result;
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/store.h b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/store.h
new file mode 100644
index 0000000..b1fbea7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/store.h
@@ -0,0 +1,39 @@
+#ifndef PURE_STORE_H
+#define PURE_STORE_H
+#include "flow.h"
+#include <stdint.h>
+
+#define PURE_OBJECT_LIMIT ((2u * 6u + 32u) * 32768u + 8192u)
+typedef enum {
+ PURE_OK, PURE_NOT_FOUND, PURE_CONFLICT, PURE_BUSY, PURE_BUDGET,
+ PURE_LIMIT, PURE_STORE_ERROR, PURE_UNCERTAIN
+} PureResult;
+typedef struct {
+ void *mapping;
+ size_t mapped_size, object_size;
+ PureSpan body;
+ int64_t revision;
+} PureStoredView;
+
+PureResult pure_store_init(const char *path);
+PureResult pure_store_get(const char *path, const char *key, size_t available,
+ PureStoredView *out);
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out);
+/* Inspect once: guards and mapping refer to the same immutable file version.
+ * minimum preserves bounds checks from eliminated intermediate views. */
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out);
+void pure_store_release(PureStoredView *);
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision);
+
+/* Fault hooks exist only in the separately built unit-test binary. */
+typedef enum {
+ PURE_AFTER_HEADER, PURE_BEFORE_FILE_SYNC, PURE_BEFORE_RENAME, PURE_BEFORE_DIR_SYNC
+} PureStoreStage;
+#ifdef PURE_STORE_TEST
+int pure_store_test_fault(PureStoreStage stage);
+#endif
+#endif
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/test-flow.c b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/test-flow.c
new file mode 100644
index 0000000..5ff028d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/test-flow.c
@@ -0,0 +1,183 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static int failed_stage = -1;
+static bool crash_at_stage;
+int pure_store_test_fault(PureStoreStage stage) {
+ if ((int)stage != failed_stage) return 0;
+ if (crash_at_stage) _exit(77);
+ return 1;
+}
+typedef struct { unsigned char *bytes; unsigned releases; } Owner;
+static void release(void *raw) {
+ Owner *owner = raw;
+ free(owner->bytes);
+ owner->bytes = NULL;
+ ++owner->releases;
+}
+
+static void transfers(void) {
+ Owner owner = {.bytes = malloc(5)};
+ CHECK(owner.bytes);
+ memcpy(owner.bytes, "a\0bcd", 5);
+ PureTransfer transfer = {0};
+ pure_transfer_init(&transfer, (PureSpan){(const unsigned char *)"head", 4},
+ (PureSpan){owner.bytes, 5}, &owner, release);
+ CHECK(!pure_transfer_consume(&transfer, 5));
+ CHECK(transfer.active && !owner.releases);
+ CHECK(pure_transfer_consume(&transfer, 0));
+ unsigned char received[9];
+ size_t used = 0;
+ while (transfer.active) {
+ PureSpan span = pure_transfer_next(&transfer, 2);
+ CHECK(span.size && span.size <= 2);
+ memcpy(received + used, span.data, span.size);
+ used += span.size;
+ CHECK(pure_transfer_consume(&transfer, span.size));
+ CHECK((used == 9) == (owner.releases == 1));
+ }
+ CHECK(used == 9 && !memcmp(received, "heada\0bcd", 9));
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 1 && !pure_transfer_consume(&transfer, 0));
+ owner.bytes = malloc(3);
+ CHECK(owner.bytes);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){owner.bytes, 3}, &owner, release);
+ CHECK(pure_transfer_consume(&transfer, 1));
+ pure_transfer_abort(&transfer);
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 2 && !transfer.active);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){0}, &owner, release);
+ CHECK(owner.releases == 3 && !transfer.active);
+}
+
+static void storage(const char *path) {
+ CHECK(pure_store_init(path) == PURE_OK);
+ PureStoredView first, second;
+ CHECK(pure_store_get(path, "missing", 100, &first) == PURE_NOT_FOUND);
+ CHECK(!first.mapping && !first.mapped_size);
+ static const unsigned char original[] = {0, 1, 2, 255, 17};
+ static const unsigned char updated[] = {9, 8, 7};
+ int64_t revision;
+ CHECK(pure_store_put(path, "work", 0, (PureSpan){original, sizeof(original)}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ CHECK(pure_store_get(path, "work", sizeof(original) - 1, &first) == PURE_BUDGET);
+ CHECK(!first.mapping && !first.mapped_size);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 3, &first) == PURE_OK);
+ CHECK(first.object_size == sizeof(original) && first.body.size == 3 && !memcmp(first.body.data, original + 1, 3));
+ pure_store_release(&first);
+ CHECK(pure_store_get_range(path, "work", SIZE_MAX, 1, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, SIZE_MAX, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 2, &first) == PURE_BUDGET);
+ CHECK(pure_store_get_range(path, "work", sizeof(original), 0, 0, &first) == PURE_OK);
+ CHECK(!first.mapped_size && !first.body.size);
+ pure_store_release(&first);
+ CHECK(pure_store_get(path, "work", sizeof(original), &first) == PURE_OK);
+ CHECK(first.body.size == sizeof(original) && first.revision == 1);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 2);
+ CHECK(!memcmp(first.body.data, original, sizeof(original)));
+ CHECK(pure_store_get(path, "work", 100, &second) == PURE_OK);
+ CHECK(second.revision == 2 && second.body.size == sizeof(updated));
+ CHECK(!memcmp(second.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ pure_store_release(&first);
+ pure_store_release(&second);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){original, sizeof(original)}, &revision) == PURE_CONFLICT);
+ CHECK(revision == 2);
+
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 2 && !memcmp(first.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == 3);
+ failed_stage = -1;
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_CONFLICT);
+
+ /* A crashed unpublished writer leaves only a private file. A new publisher
+ * must still use the previous committed version, never an incomplete body. */
+ pid_t child = fork();
+ CHECK(child >= 0);
+ if (!child) {
+ failed_stage = PURE_AFTER_HEADER;
+ crash_at_stage = true;
+ pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision);
+ _exit(78);
+ }
+ int status;
+ CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 77);
+ CHECK(pure_store_init(path) == PURE_OK);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 4);
+
+ char file[320];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ CHECK(fd >= 0);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_put(path, "work", INT64_MAX, (PureSpan){original, sizeof(original)}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_put(path, "empty", 0, (PureSpan){0}, &revision) == PURE_OK);
+ CHECK(pure_store_get(path, "empty", 0, &first) == PURE_OK && first.body.size == 0);
+ pure_store_release(&first);
+
+ /* Range mapping crosses page boundaries without copying a whole object. */
+ long page = sysconf(_SC_PAGESIZE);
+ CHECK(page >= 128 && (size_t)page <= PURE_OBJECT_LIMIT / 3);
+ size_t size = (size_t)page * 3, offset = (size_t)page + 13, length = (size_t)page + 105;
+ unsigned char *bytes = malloc(size);
+ CHECK(bytes);
+ for (size_t i = 0; i < size; ++i) bytes[i] = (unsigned char)((i * 17u) ^ (i >> 8) ^ (i >> 16));
+ CHECK(pure_store_put(path, "range", 0, (PureSpan){bytes, size}, &revision) == PURE_OK);
+ CHECK(pure_store_get_range(path, "range", offset, length, length, &first) == PURE_OK);
+ CHECK(first.body.size == length && !memcmp(first.body.data, bytes + offset, length));
+ pure_store_release(&first);
+ free(bytes);
+ snprintf(file, sizeof(file), "%s/obj-broken", path);
+ fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0600);
+ CHECK(fd >= 0 && write(fd, "incomplete", 10) == 10 && close(fd) == 0);
+ CHECK(pure_store_get(path, "broken", 100, &first) == PURE_STORE_ERROR && !first.mapped_size);
+ CHECK(pure_store_put(path, "broken", 0, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_init(file) == PURE_STORE_ERROR);
+ struct stat info;
+ CHECK(stat(file, &info) == 0 && info.st_size == 10);
+}
+
+int main(void) {
+ transfers();
+ char directory[] = "/tmp/pure-connection-unit-XXXXXX";
+ CHECK(mkdtemp(directory));
+ char path[256];
+ snprintf(path, sizeof(path), "%s/store", directory);
+ storage(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ CHECK(rmdir(directory) == 0);
+ puts("{\"transfer\":\"partial-consumption-and-single-release\","
+ "\"storage\":\"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty\"}");
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/test-program.c b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/test-program.c
new file mode 100644
index 0000000..b8deeba
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/connections/test-program.c
@@ -0,0 +1,111 @@
+#include "program.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static PureProgram parse(const char *source) {
+ PureProgram program;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &program, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return program;
+}
+static void invalid(const char *source) {
+ PureProgram program;
+ memset(&program, 0x5a, sizeof(program));
+ unsigned char original[sizeof(program)];
+ memcpy(original, &program, sizeof(program));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &program, error, sizeof(error)));
+ CHECK(*error && !memcmp(original, &program, sizeof(program)));
+}
+int main(void) {
+ char source[4096];
+ snprintf(source, sizeof(source), "%s %s", get, put);
+ PureProgram plan = parse(source);
+ CHECK(plan.read.whole && plan.write.whole && !plan.reply_input);
+ CHECK(!plan.view_definitions && !plan.read_required && !plan.input_required);
+ snprintf(source, sizeof(source), "%s on put { let a = range(request.body, 2, 10); "
+ "let b = range(a, 3, 4); let alias = b; "
+ "let saved = store.write(request.key, request.revision, alias); reply(saved, b); }", get);
+ plan = parse(source);
+ CHECK(plan.write.offset == 5 && plan.write.length == 4 && !plan.write.whole);
+ CHECK(plan.reply.offset == 5 && plan.reply.length == 4 && plan.reply_input);
+ CHECK(plan.input_required == 12 && plan.range_definitions == 2 && plan.view_definitions == 3);
+ /* Ordered reference views keep even unused bounds failures observable. */
+ unsigned char bytes[160];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 7);
+ size_t comparisons = 0;
+ for (size_t a = 0; a < 4; ++a) for (size_t b = 0; b < 6; ++b)
+ for (size_t c = 0; c <= b; ++c) for (size_t d = 0; d <= b - c; ++d) {
+ size_t unused_end = (a + b + c) % 12;
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); "
+ "let unused = range(o.body, %zu, 0); let first = range(o.body, %zu, %zu); "
+ "let second = range(first, %zu, %zu); reply(o, second); } %s",
+ unused_end, a, b, c, d, put);
+ plan = parse(source);
+ for (size_t n = 0; n < 16; ++n) {
+ bool reference_ok = unused_end <= n && a <= n && b <= n - a;
+ PureSpan selected;
+ bool prepared_ok = n >= plan.read_required &&
+ pure_region_span(plan.read, (PureSpan){bytes, n}, &selected);
+ CHECK(reference_ok == prepared_ok);
+ if (reference_ok) {
+ CHECK(selected.size == d);
+ CHECK(!d || !memcmp(selected.data, bytes + a + c, d));
+ }
+ ++comparisons;
+ }
+ }
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); reply(o); } %s", put);
+ plan = parse(source);
+ CHECK(!plan.read.whole && !plan.read.length);
+ const char *bad_get[] = {
+ "on get { let o = store.read(request.key); let x = range(o.body, 0, 2); let y = range(x, 2, 1); reply(o, y); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 184467440737095516160, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 1449984, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let o = o.body; reply(o); }",
+ "on get { let o = store.read(request.key); let x = x; reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = store.read(request.key); reply(x); }",
+ "on get { let o = store.read(request.key); reply(o, request.body); }",
+ "on get { let o = store.read(request.key); let x = o.body; reply(x); }",
+ "on get { let o = store.read(request.key); reply(o.body); }",
+ "on get { let o = store.read(request.key); reply(o); let x = o.body; }",
+ "on get { let o = store.read(request.key); reply(o);", "on get {}"
+ };
+ for (size_t i = 0; i < sizeof(bad_get) / sizeof(*bad_get); ++i) {
+ snprintf(source, sizeof(source), "%s %s", bad_get[i], put); invalid(source);
+ }
+ const char *bad_put[] = {
+ "on put { let s = store.write(request.key, request.revision, request.body); let b = range(request.body, 0, 1); reply(s, b); }",
+ "on put { let s = store.write(request.key, request.revision, request.body); reply(s, s.body); }",
+ "on put { let s = store.read(request.key); reply(s); }"
+ };
+ for (size_t i = 0; i < sizeof(bad_put) / sizeof(*bad_put); ++i) {
+ snprintf(source, sizeof(source), "%s %s", get, bad_put[i]); invalid(source);
+ }
+ invalid(get);
+ snprintf(source, sizeof(source), "%s %s %s", get, get, put); invalid(source);
+ snprintf(source, sizeof(source), "%s %s garbage", get, put); invalid(source);
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); ");
+ for (size_t i = 0; i < 32; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let x%zu = o.body; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "reply(o); } %s", put); invalid(source);
+ char oversized[PURE_PROGRAM_LIMIT + 1];
+ memset(oversized, ' ', sizeof(oversized));
+ char error[160];
+ CHECK(!pure_program_parse(oversized, sizeof(oversized), &plan, error, sizeof(error)));
+ const char embedded[] = "on get\0{}";
+ CHECK(!pure_program_parse(embedded, sizeof(embedded) - 1, &plan, error, sizeof(error)));
+ PureSpan selected;
+ CHECK(pure_region_span((PureRegion){0}, (PureSpan){0}, &selected) && !selected.data && !selected.size);
+ printf("{\"program\":\"prepare-views-preserve-guards-types-effects-and-atomic-install\","
+ "\"boundary_semantic_comparisons\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/cli.mjs b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/cli.mjs
new file mode 100644
index 0000000..b67f4d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/cli.mjs
@@ -0,0 +1,127 @@
+#!/usr/bin/env node
+import { readFile, writeFile } from 'node:fs/promises';
+import { createInterface } from 'node:readline';
+import { createRuntime } from './web/runtime.mjs';
+import { parseProject } from './web/project.mjs';
+import { remoteTarget, pushProject, pullProject } from './remote.mjs';
+
+const help = `Pure authoring workbench · 같은 정의와 Zig 실행기
+ load PATH .pure 파일을 적용 (같은 이름의 상태 보존)
+ down NAME 정의한 입력 누르기
+ up NAME 정의한 입력 놓기
+ point NAME PHASE X Y 좌표 입력 (down / move / up / cancel)
+ point-target NAME VIEW PHASE X Y 그룹의 대상에 좌표 입력
+ change NAME VALUE 숫자 입력 전달
+ frame [1..600] 시간 진행, 1프레임 = 1/60초
+ show 상태와 도형 출력
+ limits C H W 표시 캐시(0..32)·변경 기록(0..8)·작업량(0..4294967295) 설정
+ forget [PART] 표시 기록 삭제: all, values, history (상태는 유지)
+ costs 마지막 표시 계산의 작업량·명령 수·캐시 적중 출력
+ reset 현재 정의의 초기 상태로
+ save PATH 적용한 정의를 저장
+ save-project PATH 적용 코드와 현재 배치를 JSON으로 저장
+ restore PATH 저장한 배치를 복원 (초안이 있으면 파일에 보존)
+ connect URL KEY 로컬 네이티브 저장 서버의 작업물에 연결
+ push [REVISION] 현재 배치를 저장 (첫 생성은 push 0, 충돌 시 기존 값 유지)
+ pull 원격 배치를 검증·복원하고 revision 기억
+ help / quit
+브라우저와 별도 인스턴스입니다. 임의 JavaScript는 실행하지 않습니다.`;
+
+async function main() {
+ const args = process.argv.slice(2);
+ if (args.includes('--help')) { console.log(help); return; }
+ if (args.length > 1) throw new Error('사용법: node cli.mjs [project.pure]');
+ const runtime = await createRuntime(await readFile(new URL('./web/core.wasm', import.meta.url)));
+ let savedDraft = null;
+ let remote = null, remoteRevision = null;
+ async function loadFile(path, restoreOnly = false) {
+ const content = await readFile(path, 'utf8');
+ if (restoreOnly || path.toLowerCase().endsWith('.json')) {
+ const project = parseProject(content);
+ if (project.version === 2) {
+ savedDraft = runtime.restoreDocument(project).draft;
+ return;
+ }
+ if (restoreOnly) throw new Error('현재 배치가 포함된 version 2 파일이 필요합니다.');
+ runtime.apply(project.source);
+ } else runtime.apply(content);
+ savedDraft = null;
+ }
+ if (args[0]) await loadFile(args[0]); else runtime.apply('');
+ const terminal = createInterface({ input: process.stdin, output: process.stdout, terminal: Boolean(process.stdin.isTTY) });
+ if (process.stdin.isTTY) console.log(help);
+ terminal.setPrompt('pure> ');
+ if (process.stdin.isTTY) terminal.prompt();
+ for await (const line of terminal) {
+ try {
+ const match = /^(\S+)(?:\s+(.+))?$/.exec(line.trim());
+ const name = match?.[1] || 'show';
+ const arg = match?.[2];
+ if (name === 'quit') { terminal.close(); break; }
+ if (name === 'help') console.log(help);
+ else if (name === 'costs' && !arg) console.log(JSON.stringify({ evaluation: runtime.evaluationStats() }));
+ else {
+ if (name === 'load' && arg) await loadFile(arg);
+ else if (name === 'restore' && arg) await loadFile(arg, true);
+ else if (name === 'connect' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('connect URL KEY 형식을 사용하세요.');
+ remote = remoteTarget(parts[0], parts[1]);
+ remoteRevision = null;
+ console.log(JSON.stringify({ remote: remote.href }));
+ } else if (name === 'push') {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const expected = arg ?? remoteRevision;
+ if (expected === null) throw new Error('먼저 pull로 버전을 읽거나 push 0으로 새 작업물을 만드세요.');
+ remoteRevision = await pushProject(remote, expected, runtime.exportDocument(savedDraft ?? undefined));
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, stored: true }));
+ } else if (name === 'pull' && !arg) {
+ if (!remote) throw new Error('먼저 connect URL KEY로 연결하세요.');
+ const loaded = await pullProject(remote);
+ savedDraft = runtime.restoreDocument(loaded.project).draft;
+ remoteRevision = loaded.revision;
+ console.log(JSON.stringify({ remote: remote.href, revision: remoteRevision, restored: true }));
+ }
+ else if (name === 'save-project' && arg) await writeFile(arg, JSON.stringify(runtime.exportDocument(savedDraft ?? undefined), null, 2) + '\n', {flag:'wx'});
+ else if (name === 'save' && arg) await writeFile(arg, runtime.exportProject().source, { flag: 'wx' });
+ else if (name === 'down' && arg) runtime.down(arg, 'terminal');
+ else if (name === 'up' && arg) runtime.up(arg, 'terminal');
+ else if (name === 'point' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 4) throw new Error('point NAME PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[1], Number(parts[2]), Number(parts[3]), 'terminal');
+ } else if (name === 'point-target' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 5) throw new Error('point-target NAME VIEW PHASE X Y 형식을 사용하세요.');
+ runtime.point(parts[0], parts[2], Number(parts[3]), Number(parts[4]), 'terminal', parts[1]);
+ } else if (name === 'change' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 2) throw new Error('change NAME VALUE 형식을 사용하세요.');
+ runtime.change(parts[0], Number(parts[1]), 'terminal');
+ } else if (name === 'frame') {
+ if (arg !== undefined && !/^\d+$/.test(arg)) throw new Error('frame 1..600 정수를 입력하세요.');
+ const count = arg === undefined ? 1 : Number(arg);
+ if (count < 1 || count > 600) throw new Error('frame 1..600 정수를 입력하세요.');
+ runtime.frame(count);
+ } else if (name === 'reset' && !arg) runtime.reset();
+ else if (name === 'limits' && arg) {
+ const parts = arg.split(/\s+/);
+ if (parts.length !== 3 || parts.some(part => !/^\d+$/.test(part)))
+ throw new Error('limits C H W 정수 세 개를 입력하세요.');
+ const [cacheEntries, historyEntries, workLimit] = parts.map(Number);
+ runtime.configureEvaluation({ cacheEntries, historyEntries, workLimit });
+ } else if (name === 'forget') runtime.forgetEvaluation(arg || 'all');
+ else if (name !== 'show' || arg) throw new Error('명령 형식을 확인하세요. help로 안내를 볼 수 있습니다.');
+ const result = runtime.snapshot();
+ console.log(JSON.stringify(result));
+ if (result.lastError && !process.stdin.isTTY) process.exitCode = 1;
+ }
+ } catch (error) {
+ console.error(`${error.line ? `${error.line}:${error.column || 1} ` : ''}${error.message}`);
+ if (!process.stdin.isTTY) process.exitCode = 1;
+ }
+ if (process.stdin.isTTY) terminal.prompt();
+ }
+}
+
+main().catch((error) => { console.error(error.message); process.exitCode = 1; });
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/examples/direct.pure b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/examples/direct.pure
new file mode 100644
index 0000000..b29721c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/examples/direct.pure
@@ -0,0 +1,47 @@
+# 도형을 잡은 위치를 유지해 이동합니다. 취소하면 잡기 전 위치로 돌아갑니다.
+state x = 80
+state y = 160
+state grab_x = 0
+state grab_y = 0
+state start_x = 80
+state start_y = 160
+state dragging = 0
+
+input drag = pointer(tile)
+input left = ArrowLeft
+input right = ArrowRight
+
+box left_area(20, 100, 280, 220, "#233a31")
+box right_area(340, 100, 280, 220, "#343b25")
+box tile(x, y, 56, 44, "#c9f08b")
+text horizontal(30, 45, x, "x: ")
+text vertical(180, 45, y, "y: ")
+text region(350, 70, x >= 320, "오른쪽 영역: ")
+text active(30, 75, dragging, "잡고 있음: ")
+
+on drag.down {
+ start_x = x
+ start_y = y
+ grab_x = event_x - x
+ grab_y = event_y - y
+ dragging = 1
+}
+on drag.move {
+ x = clamp(event_x - grab_x, 20, 564)
+ y = clamp(event_y - grab_y, 100, 276)
+}
+on drag.up {
+ # 놓기는 마지막으로 표시한 위치를 확정합니다.
+ dragging = 0
+}
+on drag.cancel {
+ x = start_x
+ y = start_y
+ dragging = 0
+}
+on left.down {
+ if dragging == 0 { x = max(20, x - 10) }
+}
+on right.down {
+ if dragging == 0 { x = min(564, x + 10) }
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/remote.mjs b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/remote.mjs
new file mode 100644
index 0000000..6ee6a59
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/remote.mjs
@@ -0,0 +1,89 @@
+import http from 'node:http';
+import { MAX_PROJECT_BYTES, parseProject } from './web/project.mjs';
+
+const maxRevision = 9223372036854775807n;
+function revisionText(value, allowZero = false) {
+ if (typeof value !== 'string' || !/^(0|[1-9]\d*)$/.test(value) ||
+ value.length > 19 || BigInt(value) > maxRevision || (!allowZero && value === '0'))
+ throw new Error('revision은 범위 안의 정수 문자열이어야 합니다.');
+ return value;
+}
+
+export function remoteTarget(base, key) {
+ const url = new URL(base);
+ if (url.protocol !== 'http:' || !['127.0.0.1', 'localhost'].includes(url.hostname) ||
+ url.username || url.password || url.pathname !== '/' || url.search || url.hash)
+ throw new Error('현재 연결 호스트는 로컬 http://127.0.0.1:PORT 형식을 사용합니다.');
+ if (!/^[A-Za-z0-9_-]{1,64}$/.test(key)) throw new Error('작업물 이름은 영문·숫자·_·- 1~64자입니다.');
+ url.hostname = '127.0.0.1';
+ url.pathname = `/objects/${key}`;
+ return url;
+}
+
+function request(url, method, body, headers = {}) {
+ return new Promise((resolve, reject) => {
+ let done = false;
+ const finish = (error, value) => {
+ if (done) return;
+ done = true;
+ clearTimeout(deadline);
+ if (error) reject(error); else resolve(value);
+ };
+ const req = http.request(url, { method, agent: false, headers: { ...headers,
+ 'Content-Length': body?.byteLength ?? 0, Connection: 'close' } }, (res) => {
+ const chunks = [];
+ let size = 0;
+ res.on('data', (chunk) => {
+ size += chunk.length;
+ if (size > MAX_PROJECT_BYTES) {
+ const error = new Error('서버 작업물이 허용 크기를 넘었습니다.');
+ finish(error);
+ res.destroy(error);
+ req.destroy(error);
+ } else chunks.push(chunk);
+ });
+ res.on('error', (error) => finish(error));
+ res.on('aborted', () => finish(new Error('응답이 완료되기 전에 연결이 끊겼습니다.')));
+ res.on('end', () => {
+ if (res.statusCode !== 200) {
+ const error = new Error(`원격 작업 실패: ${res.statusCode} ${res.headers['x-pure-error'] ?? ''}`.trim());
+ error.status = res.statusCode;
+ error.etag = res.headers.etag;
+ finish(error);
+ return;
+ }
+ try {
+ const match = /^"([1-9]\d*)"$/.exec(res.headers.etag ?? '');
+ if (!match) throw new Error('서버의 revision 응답이 올바르지 않습니다.');
+ const revision = revisionText(match[1]);
+ finish(null, { revision, bytes: Buffer.concat(chunks, size) });
+ } catch (error) { finish(error); }
+ });
+ });
+ const deadline = setTimeout(() => {
+ const error = new Error('원격 작업 시간 초과: 저장 완료 여부는 다시 확인해야 합니다.');
+ finish(error);
+ req.destroy(error);
+ }, 12000);
+ req.on('error', (error) => finish(error));
+ req.end(body);
+ });
+}
+
+export async function pushProject(target, expected, project) {
+ revisionText(expected, true);
+ const text = JSON.stringify(project);
+ parseProject(text);
+ const body = Buffer.from(text, 'utf8');
+ const headers = expected === '0' ? { 'If-None-Match': '*' } : { 'If-Match': `"${expected}"` };
+ const result = await request(target, 'PUT', body, headers);
+ return result.revision;
+}
+
+export async function pullProject(target) {
+ const result = await request(target, 'GET');
+ const text = new TextDecoder('utf-8', { fatal: true }).decode(result.bytes);
+ const project = parseProject(text);
+ if (project.version !== 2) throw new Error('현재 배치를 포함한 version 2 작업물이 필요합니다.');
+ return { project, revision: result.revision };
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/compiler.mjs b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/compiler.mjs
new file mode 100644
index 0000000..6aec335
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/compiler.mjs
@@ -0,0 +1,496 @@
+// Pure's experimental scalar interaction language. No host code is evaluated.
+const LIMITS = Object.freeze({ sourceBytes: 32768, states: 32, inputs: 8,
+ views: 24, handlers: 64, instructions: 512, depth: 64, stack: 64 });
+const RESERVED = new Set(['frame', 'dt', 'event_x', 'event_y', 'event_value', 'min', 'max', 'clamp']);
+const BINARY = new Map([
+ ['||', [1, 15]], ['&&', [2, 14]], ['==', [3, 12]], ['!=', [3, 13]],
+ ['<', [4, 8]], ['<=', [4, 9]], ['>', [4, 10]], ['>=', [4, 11]],
+ ['+', [5, 3]], ['-', [5, 4]], ['*', [6, 5]], ['/', [6, 6]],
+]);
+const FUNCTIONS = { min: [2, 17], max: [2, 18], clamp: [3, 19] };
+const VIEW_FIELDS = { box: ['x', 'y', 'width', 'height'],
+ circle: ['x', 'y', 'radius'], text: ['x', 'y', 'value'] };
+
+function fail(token, message) {
+ const error = new Error(`${message} (${token.line}:${token.column})`);
+ error.line = token.line;
+ error.column = token.column;
+ throw error;
+}
+
+function lex(source) {
+ const tokens = [];
+ let offset = 0, line = 1, column = 1;
+ const advance = () => {
+ const char = source[offset++];
+ if (char === '\n') { line++; column = 1; } else column++;
+ return char;
+ };
+ while (offset < source.length) {
+ const char = source[offset];
+ if (char === ' ' || char === '\t' || char === '\r') { advance(); continue; }
+ if (char === '#') { while (offset < source.length && source[offset] !== '\n') advance(); continue; }
+ const token = { line, column };
+ if (char === '\n') { advance(); tokens.push({ ...token, kind: 'nl' }); continue; }
+ if (char === '"') {
+ advance();
+ let value = '', closed = false;
+ while (offset < source.length) {
+ const next = advance();
+ if (next === '"') { closed = true; break; }
+ if (next === '\n' || next === '\r') fail(token, 'Strings must fit on one line');
+ if (next === '\\') {
+ const escaped = advance();
+ const escapes = { n: '\n', r: '\r', t: '\t', '"': '"', '\\': '\\' };
+ if (!Object.hasOwn(escapes, escaped)) fail(token, 'Unsupported string escape');
+ value += escapes[escaped];
+ } else value += next;
+ }
+ if (!closed) fail(token, 'Unterminated string');
+ tokens.push({ ...token, kind: 'string', value }); continue;
+ }
+ const remaining = source.slice(offset);
+ const number = remaining.match(/^(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/);
+ if (number) {
+ const value = Number(number[0]);
+ if (!Number.isFinite(value)) fail(token, 'Number must be finite');
+ for (let i = 0; i < number[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'number', value }); continue;
+ }
+ const name = remaining.match(/^[A-Za-z_][A-Za-z_0-9]*/);
+ if (name) {
+ for (let i = 0; i < name[0].length; i++) advance();
+ tokens.push({ ...token, kind: 'name', value: name[0] }); continue;
+ }
+ const pair = source.slice(offset, offset + 2);
+ if (['<=', '>=', '==', '!=', '&&', '||'].includes(pair)) {
+ advance(); advance(); tokens.push({ ...token, kind: pair }); continue;
+ }
+ if ('=+-*/!<>(){},.;:'.includes(char)) {
+ advance(); tokens.push({ ...token, kind: char }); continue;
+ }
+ fail(token, `Unexpected character ${JSON.stringify(char)}`);
+ }
+ tokens.push({ kind: 'eof', line, column });
+ return tokens;
+}
+
+class Parser {
+ constructor(tokens) { this.tokens = tokens; this.position = 0; this.depth = 0; }
+ peek() { return this.tokens[this.position]; }
+ take() { return this.tokens[this.position++]; }
+ is(kind, value) { return this.peek().kind === kind && (value === undefined || this.peek().value === value); }
+ expect(kind, description = kind) {
+ if (!this.is(kind)) fail(this.peek(), `Expected ${description}`);
+ return this.take();
+ }
+ newlines() { while (this.is('nl')) this.take(); }
+ separators() { while (this.is('nl') || this.is(';')) this.take(); }
+ end() {
+ if (!['nl', ';', '}', 'eof'].includes(this.peek().kind)) fail(this.peek(), 'Expected newline or semicolon');
+ this.separators();
+ }
+ reference(token) {
+ if (!this.is('.')) return token.value;
+ this.take();
+ return `${token.value}.${this.expect('name', 'field name').value}`;
+ }
+ initial() {
+ let sign = 1;
+ if (this.is('-') || this.is('+')) sign = this.take().kind === '-' ? -1 : 1;
+ return sign * this.expect('number', 'numeric state initializer').value;
+ }
+ node(token, properties, children = []) {
+ const depth = 1 + Math.max(0, ...children.map(child => child.depth));
+ if (depth > LIMITS.depth) fail(token, 'Expression nesting exceeds 64');
+ return { token, depth, ...properties };
+ }
+ expression(minimum = 0, multiline = false) {
+ if (++this.depth > LIMITS.depth) fail(this.peek(), 'Expression nesting exceeds 64');
+ if (multiline) this.newlines();
+ const token = this.take();
+ let left;
+ if (token.kind === 'number') left = this.node(token, { kind: 'constant', value: token.value });
+ else if (token.kind === '-' || token.kind === '!') {
+ const child = this.expression(7, multiline);
+ left = this.node(token, { kind: 'unary', op: token.kind === '-' ? 7 : 16, child }, [child]);
+ } else if (token.kind === '(') {
+ left = this.expression(0, true); this.newlines(); this.expect(')');
+ } else if (token.kind === 'name') {
+ if (Object.hasOwn(FUNCTIONS, token.value) && this.is('(')) {
+ this.take();
+ const args = [];
+ this.newlines();
+ if (!this.is(')')) {
+ for (;;) {
+ args.push(this.expression(0, true)); this.newlines();
+ if (!this.is(',')) break;
+ this.take();
+ }
+ }
+ this.expect(')');
+ if (args.length !== FUNCTIONS[token.value][0]) fail(token, `${token.value} expects ${FUNCTIONS[token.value][0]} arguments`);
+ left = this.node(token, { kind: 'call', op: FUNCTIONS[token.value][1], args }, args);
+ } else left = this.node(token, { kind: 'reference', name: this.reference(token) });
+ } else fail(token, 'Expected a number, state, or expression');
+ for (;;) {
+ if (multiline) this.newlines();
+ const entry = BINARY.get(this.peek().kind);
+ if (!entry || entry[0] < minimum) break;
+ const operator = this.take();
+ const right = this.expression(entry[0] + 1, multiline);
+ left = this.node(operator, { kind: 'binary', op: entry[1], left, right }, [left, right]);
+ }
+ this.depth--;
+ return left;
+ }
+ block(depth = 0) {
+ if (depth >= LIMITS.depth) fail(this.peek(), 'Handler nesting exceeds 64');
+ this.newlines(); this.expect('{'); this.separators();
+ const statements = [];
+ while (!this.is('}')) {
+ const token = this.expect('name', 'assignment, if, or closing brace');
+ if (token.value === 'if' && !this.is('=')) {
+ const condition = this.expression();
+ const body = this.block(depth + 1);
+ statements.push({ kind: 'if', token, condition, body });
+ } else {
+ const name = this.reference(token);
+ this.expect('=');
+ statements.push({ kind: 'assign', token, name, expression: this.expression() });
+ }
+ this.end();
+ }
+ this.take();
+ return statements;
+ }
+ parse() {
+ const declarations = [];
+ this.separators();
+ while (!this.is('eof')) {
+ const token = this.expect('name', 'declaration');
+ const kind = token.value;
+ if (kind === 'state') {
+ const name = this.expect('name', 'state name'); this.expect('=');
+ declarations.push({ kind, token, name, initial: this.initial() });
+ } else if (kind === 'record') {
+ const name = this.expect('name', 'record type'); this.newlines(); this.expect('{'); this.separators();
+ const fields = [];
+ while (!this.is('}')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,fields});
+ } else if (kind === 'item') {
+ const name = this.expect('name', 'item name'); this.expect('=');
+ const type = this.expect('name', 'record type'); this.expect('('); this.newlines();
+ const fields = [];
+ while (!this.is(')')) {
+ const field = this.expect('name', 'field name'); this.expect('=');
+ fields.push({name:field, initial:this.initial()}); this.newlines();
+ if (!this.is(',')) break;
+ this.take(); this.newlines();
+ }
+ this.expect(')'); declarations.push({kind,token,name,type,fields});
+ } else if (kind === 'rule') {
+ const name = this.expect('name', 'rule name'); this.expect('(');
+ const parameter = this.expect('name', 'record parameter'); this.expect(':');
+ const type = this.expect('name', 'record type'); this.expect(')');
+ declarations.push({kind,token,name,parameter,type,body:this.block()});
+ } else if (kind === 'input') {
+ const name = this.expect('name', 'input name'); this.expect('=');
+ const key = this.expect('name', 'keyboard code or pointer(view)');
+ if (key.value === 'value') {
+ declarations.push({kind,token,name,valueInput:true}); this.end(); continue;
+ }
+ if (key.value === 'pointer') {
+ if (this.is('{')) {
+ this.take(); this.separators(); const routes = [];
+ while (!this.is('}')) {
+ const target = this.expect('name', 'view ID'); this.expect(':');
+ const item = this.expect('name', 'item name'); routes.push({target,item}); this.end();
+ }
+ this.take(); declarations.push({kind,token,name,routes}); this.end(); continue;
+ }
+ this.expect('(');
+ const target = this.expect('name', 'view ID'); this.expect(')');
+ declarations.push({ kind, token, name, target });
+ this.end(); continue;
+ }
+ if (!/^(?:Space|Enter|Arrow(?:Left|Right|Up|Down)|Key[A-Z]|Digit[0-9])$/.test(key.value)) fail(key, 'Unsupported keyboard code');
+ declarations.push({ kind, token, name, key });
+ } else if (Object.hasOwn(VIEW_FIELDS, kind)) {
+ const name = this.expect('name', 'view ID'); this.expect('(');
+ const expressions = [];
+ for (let i = 0; i < VIEW_FIELDS[kind].length; i++) {
+ if (i) { this.newlines(); this.expect(','); }
+ expressions.push(this.expression(0, true));
+ }
+ this.newlines();
+ let color, prefix = '';
+ if (kind !== 'text') {
+ this.expect(','); this.newlines();
+ const value = this.expect('string', 'literal hex color');
+ if (!/^#[0-9a-fA-F]{6}$/.test(value.value)) fail(value, 'Color must use six hexadecimal digits, such as "#356548"');
+ color = value.value;
+ } else if (this.is(',')) { this.take(); this.newlines(); prefix = this.expect('string', 'literal text prefix').value; }
+ this.newlines(); this.expect(')');
+ declarations.push({ kind: 'view', type: kind, token, name, expressions, color, prefix });
+ } else if (kind === 'on') {
+ const event = this.expect('name', 'input name or frame');
+ let edge;
+ if (event.value !== 'frame') {
+ this.expect('.'); edge = this.expect('name', 'down, up, move or cancel');
+ if (!['down', 'up', 'move', 'cancel', 'change'].includes(edge.value)) fail(edge, 'Expected down or up, move, cancel or change');
+ }
+ if (this.is('name', 'use')) {
+ this.take(); const rule = this.expect('name', 'rule name'); this.expect('(');
+ const item = this.expect('name', 'item name or input.target');
+ const argument = this.reference(item); this.expect(')');
+ declarations.push({kind:'handler',token,event,edge,rule,item,argument});
+ } else declarations.push({ kind: 'handler', token, event, edge, body: this.block() });
+ } else fail(token, `Unknown declaration ${kind}`);
+ this.end();
+ }
+ return declarations;
+ }
+}
+
+export function compile(source) {
+ if (typeof source !== 'string') fail({ line: 1, column: 1 }, 'Source must be a string');
+ const sourceBytes = new TextEncoder().encode(source).length;
+ if (sourceBytes > LIMITS.sourceBytes) fail({ line: 1, column: 1 }, 'Source exceeds 32768 UTF-8 bytes');
+ const declarations = new Parser(lex(source)).parse();
+ const program = { states: [], inputs: [], instructions: [], handlers: [], views: [], pointerTargets: [], metrics: {} };
+ const states = new Map(), inputs = new Map(), views = new Set(), keys = new Set(), targets = new Set();
+ const records = new Map(), items = new Map(), rules = new Map();
+ const scalarNames = new Set(declarations.filter(d => d.kind === 'state').map(d => d.name.value));
+ for (const declaration of declarations) {
+ if (!['record','rule'].includes(declaration.kind)) continue;
+ const {name,fields,kind} = declaration, symbols = kind === 'record' ? records : rules;
+ if (RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (kind === 'record') {
+ if (!fields.length || fields.length > 8) fail(name, 'A record needs 1..8 fields');
+ const used = new Set();
+ for (const field of fields) {
+ if (used.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ if (RESERVED.has(field.name.value)) fail(field.name, `Reserved name ${field.name.value}`);
+ used.add(field.name.value);
+ }
+ }
+ symbols.set(name.value, declaration);
+ }
+ let handlerCount = 0;
+ for (const declaration of declarations) {
+ const { kind, name, token } = declaration;
+ if (name && RESERVED.has(name.value)) fail(name, `Reserved name ${name.value}`);
+ if (kind === 'record' || kind === 'rule') continue;
+ if (kind === 'item') {
+ if (items.has(name.value) || scalarNames.has(name.value)) fail(name, `Duplicate state/item ${name.value}`);
+ const record = records.get(declaration.type.value);
+ if (!record) fail(declaration.type, `Unknown record ${declaration.type.value}`);
+ const overrides = new Map();
+ for (const field of declaration.fields) {
+ if (!record.fields.some(f => f.name.value === field.name.value)) fail(field.name, `Unknown field ${field.name.value}`);
+ if (overrides.has(field.name.value)) fail(field.name, `Duplicate field ${field.name.value}`);
+ overrides.set(field.name.value, field.initial);
+ }
+ const base = states.size;
+ for (const field of record.fields) {
+ if (states.size >= LIMITS.states) fail(name, 'At most 32 states are allowed, including item fields');
+ const qualified = `${name.value}.${field.name.value}`, index = states.size;
+ states.set(qualified,index);
+ program.states.push({name:qualified,initial:overrides.has(field.name.value) ? overrides.get(field.name.value) : field.initial,line:token.line});
+ }
+ items.set(name.value,{type:declaration.type.value,base,count:record.fields.length});
+ } else if (kind === 'state' || kind === 'input') {
+ const symbols = kind === 'state' ? states : inputs;
+ if (symbols.has(name.value)) fail(name, `Duplicate ${kind} ${name.value}`);
+ if (symbols.size >= LIMITS[`${kind}s`]) fail(name, `At most ${LIMITS[`${kind}s`]} ${kind}s are allowed`);
+ symbols.set(name.value, symbols.size);
+ if (kind === 'state') program.states.push({ name: name.value, initial: declaration.initial, line: token.line });
+ else if (declaration.valueInput) {
+ program.inputs.push({name:name.value,kind:'value',line:token.line});
+ } else if (declaration.routes) {
+ if (!declaration.routes.length) fail(name, 'A pointer group needs at least one target');
+ program.inputs.push({name:name.value, routes:[], line:token.line});
+ } else if (declaration.target) {
+ const target = declaration.target;
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ targets.add(target.value);
+ program.inputs.push({ name: name.value, target: target.value, line: token.line });
+ } else {
+ if (keys.has(declaration.key.value)) fail(declaration.key, `Duplicate keyboard code ${declaration.key.value}`);
+ keys.add(declaration.key.value);
+ program.inputs.push({ name: name.value, key: declaration.key.value, line: token.line });
+ }
+ } else if (kind === 'view') {
+ if (views.has(name.value)) fail(name, `Duplicate view ID ${name.value}`);
+ if (views.size >= LIMITS.views) fail(name, 'At most 24 views are allowed');
+ views.add(name.value);
+ } else if (++handlerCount > LIMITS.handlers) fail(token, 'At most 64 handlers are allowed');
+ }
+ for (const declaration of declarations) {
+ if (declaration.target && !views.has(declaration.target.value))
+ fail(declaration.target, `Unknown pointer target ${declaration.target.value}`);
+ }
+ const routedItems = new Set();
+ for (const declaration of declarations) {
+ if (!declaration.routes) continue;
+ const input = inputs.get(declaration.name.value), resolved = program.inputs[input];
+ let type;
+ for (const {target,item:token} of declaration.routes) {
+ if (!views.has(target.value)) fail(target, `Unknown pointer target ${target.value}`);
+ if (targets.has(target.value)) fail(target, `Duplicate pointer target ${target.value}`);
+ const item = items.get(token.value);
+ if (!item) fail(token, `Unknown item ${token.value}`);
+ if (type && type !== item.type) fail(token, 'Pointer group targets must share one record type');
+ if (routedItems.has(token.value)) fail(token, `Item ${token.value} already has a pointer route`);
+ targets.add(target.value); routedItems.add(token.value); type = item.type;
+ const route = program.pointerTargets.length;
+ if (route >= 24) fail(target, 'At most 24 pointer targets are allowed');
+ program.pointerTargets.push({input,base:item.base,count:item.count});
+ resolved.routes.push({target:target.value, item:token.value, route});
+ }
+ resolved.type = type;
+ }
+ for (const rule of rules.values()) {
+ if (!records.has(rule.type.value)) fail(rule.type, `Unknown record ${rule.type.value}`);
+ if (RESERVED.has(rule.parameter.value)) fail(rule.parameter, `Reserved name ${rule.parameter.value}`);
+ }
+ let pointHandler = false, valueHandler = false;
+ let parameters = null;
+ let parameterPrefix = null;
+ let stack = 0, maxStack = 0;
+ const emit = (op, token, arg = 0, value = 0, delta = 0) => {
+ if (program.instructions.length >= LIMITS.instructions) fail(token, 'At most 512 instructions are allowed');
+ stack += delta;
+ if (stack < 0 || stack > LIMITS.stack) fail(token, 'Expression stack exceeds 64');
+ maxStack = Math.max(maxStack, stack);
+ program.instructions.push({ op, arg, value, line: token.line });
+ };
+ const expression = (node, binding = false) => {
+ const { token } = node;
+ if (node.kind === 'constant') emit(0, token, 0, node.value, 1);
+ else if (node.kind === 'reference') {
+ if (node.name === 'event_value') {
+ if (binding || !valueHandler) fail(token, 'event_value is only available in value change handlers');
+ emit(26, token, 0, 0, 1);
+ } else if (node.name === 'event_x' || node.name === 'event_y') {
+ if (binding || !pointHandler) fail(token, 'event_x and event_y are only available in pointer handlers');
+ emit(node.name === 'event_x' ? 22 : 23, token, 0, 0, 1);
+ } else if (node.name === 'dt') {
+ if (binding) fail(token, 'dt is only available in handlers');
+ emit(2, token, 0, 0, 1);
+ } else {
+ if (parameterPrefix && node.name.startsWith(parameterPrefix) && !parameters.has(node.name))
+ fail(token, `Unknown parameter field ${node.name}`);
+ if (parameters?.has(node.name)) {
+ emit(24, token, parameters.get(node.name), 0, 1);
+ return;
+ }
+ if (!states.has(node.name)) fail(token, `Unknown state ${node.name}`);
+ emit(1, token, states.get(node.name), 0, 1);
+ }
+ } else if (node.kind === 'unary') { expression(node.child, binding); emit(node.op, token); }
+ else if (node.kind === 'binary') {
+ expression(node.left, binding); expression(node.right, binding); emit(node.op, token, 0, 0, -1);
+ } else {
+ for (const arg of node.args) expression(arg, binding);
+ emit(node.op, token, 0, 0, 1 - node.args.length);
+ }
+ };
+ const statements = body => {
+ for (const statement of body) {
+ if (statement.kind === 'assign') {
+ if (parameterPrefix && statement.name.startsWith(parameterPrefix) && !parameters.has(statement.name))
+ fail(statement.token, `Unknown parameter field ${statement.name}`);
+ const parameter = parameters?.get(statement.name);
+ if (parameter === undefined && !states.has(statement.name)) fail(statement.token, `Unknown state ${statement.name}`);
+ expression(statement.expression);
+ emit(parameter === undefined ? 20 : 25, statement.token, parameter === undefined ? states.get(statement.name) : parameter, 0, -1);
+ } else {
+ expression(statement.condition);
+ const branch = program.instructions.length;
+ emit(21, statement.token, 0, 0, -1);
+ statements(statement.body);
+ program.instructions[branch].arg = program.instructions.length;
+ }
+ }
+ };
+ const bodies = new Map();
+ function ruleBody(rule) {
+ if (bodies.has(rule.name.value)) return bodies.get(rule.name.value);
+ parameterPrefix = `${rule.parameter.value}.`;
+ parameters = new Map(records.get(rule.type.value).fields.map((field,index) => [`${rule.parameter.value}.${field.name.value}`,index]));
+ // A shared body may read coordinates; every binding is checked below.
+ pointHandler = true; valueHandler = true; stack = 0;
+ const start = program.instructions.length;
+ statements(rule.body);
+ const length = program.instructions.length - start;
+ const point = program.instructions.slice(start).some(op => op.op === 22 || op.op === 23);
+ parameters = null; parameterPrefix = null;
+ const value = program.instructions.slice(start).some(op => op.op === 26);
+ const body = {start,length,point,value}; bodies.set(rule.name.value,body); return body;
+ }
+ for (const declaration of declarations) {
+ if (declaration.kind === 'handler') {
+ let event = 0;
+ pointHandler = false; valueHandler = false;
+ if (declaration.event.value !== 'frame') {
+ if (!inputs.has(declaration.event.value)) fail(declaration.event, `Unknown input ${declaration.event.value}`);
+ const index = inputs.get(declaration.event.value), edge = declaration.edge.value;
+ pointHandler = Boolean(program.inputs[index].target || program.inputs[index].routes);
+ valueHandler = program.inputs[index].kind === 'value';
+ if (valueHandler !== (edge === 'change')) fail(declaration.edge, 'Value inputs require change; change requires a value input');
+ if (!pointHandler && (edge === 'move' || edge === 'cancel')) fail(declaration.edge, 'move and cancel require a pointer input');
+ event = edge === 'change' ? 33 + index : edge === 'move' ? 17 + index : edge === 'cancel' ? 25 + index : 1 + index * 2 + (edge === 'up' ? 1 : 0);
+ }
+ if (declaration.rule) {
+ const rule = rules.get(declaration.rule.value);
+ const routed = declaration.argument.includes('.');
+ const input = program.inputs[inputs.get(declaration.event.value)];
+ if (routed && (!input?.routes || declaration.argument !== `${declaration.event.value}.target`))
+ fail(declaration.item, 'Use the current pointer group target');
+ const item = routed ? {type:input.type, count:records.get(input.type).fields.length} : items.get(declaration.item.value);
+ if (!rule) fail(declaration.rule, `Unknown rule ${declaration.rule.value}`);
+ if (!item) fail(declaration.item, `Unknown item ${declaration.item.value}`);
+ if (item.type !== rule.type.value) fail(declaration.item, `Rule ${rule.name.value} requires ${rule.type.value}`);
+ const pointer = pointHandler, value = valueHandler;
+ const body = ruleBody(rule);
+ if (body.value && !value) fail(declaration.rule, 'Value-reading rules require a value input');
+ if (body.point && !pointer) fail(declaration.rule, 'Coordinate-reading rules require a pointer input');
+ program.handlers.push({event,start:body.start,length:body.length,line:declaration.token.line,parameterBase:routed ? 255 : item.base,parameterCount:item.count});
+ } else {
+ const start = program.instructions.length;
+ stack = 0; statements(declaration.body);
+ program.handlers.push({ event, start, length: program.instructions.length - start, line: declaration.token.line });
+ }
+ } else if (declaration.kind === 'view') {
+ const view = { id: declaration.name.value, type: declaration.type, line: declaration.token.line, bindings: {} };
+ if (view.type === 'text') view.prefix = declaration.prefix;
+ else view.color = declaration.color;
+ declaration.expressions.forEach((node, index) => {
+ const start = program.instructions.length;
+ stack = 0; expression(node, true);
+ view.bindings[VIEW_FIELDS[view.type][index]] = { start, length: program.instructions.length - start };
+ });
+ program.views.push(view);
+ }
+ }
+ // Unused definitions still receive name/type checking, but reserve no VM body.
+ for (const rule of rules.values()) {
+ if (bodies.has(rule.name.value)) continue;
+ const instructions = program.instructions, previousMax = maxStack;
+ program.instructions = [];
+ ruleBody(rule);
+ program.instructions = instructions; maxStack = previousMax;
+ }
+ program.metrics = { sourceBytes, sourceLines: source === '' ? 0 : source.split('\n').length,
+ states: states.size, inputs: inputs.size, views: views.size,
+ handlers: program.handlers.length, instructions: program.instructions.length, maxStack };
+ return program;
+}
+
+export { LIMITS };
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/core.wasm b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/core.wasm
new file mode 100644
index 0000000..79c50a8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/core.wasm
Binary files differ
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/project.mjs b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/project.mjs
new file mode 100644
index 0000000..861e0fc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/project.mjs
@@ -0,0 +1,47 @@
+import { compile } from './compiler.mjs';
+
+// Two escaped source strings plus up to 32 generated item.field names. A long
+// schema field can appear in every item without repeating in the source text.
+export const MAX_PROJECT_BYTES = (2 * 6 + 32) * 32768 + 8192;
+const encoder = new TextEncoder();
+function sourceText(value, label) {
+ if (typeof value !== 'string' || encoder.encode(value).length > 32768)
+ throw new Error(`${label}: UTF-8 32 KiB 이하의 코드가 필요합니다.`);
+ return value;
+}
+
+// No runtime mutation. Validate every saved value before opening core staging.
+export function validateDocument(document) {
+ if (!document || typeof document !== 'object' || Array.isArray(document) ||
+ document.format !== 'pure-workbench' || document.version !== 2)
+ throw new Error('배치 파일 형식이 맞지 않습니다. pure-workbench version 2가 필요합니다.');
+ const source = sourceText(document.source, '적용된 코드');
+ const draft = sourceText(Object.hasOwn(document, 'draft') ? document.draft : source, '편집 중인 코드');
+ const program = compile(source);
+ if (!Array.isArray(document.states) || document.states.length !== program.states.length)
+ throw new Error('저장된 상태 목록이 적용된 코드와 일치하지 않습니다.');
+ const values = new Map();
+ for (const entry of document.states) {
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry) || typeof entry.name !== 'string' || values.has(entry.name))
+ throw new Error('상태 이름이 잘못됐거나 중복됐습니다.');
+ const value = entry.value === '-0' ? -0 : entry.value;
+ if (typeof value !== 'number' || !Number.isFinite(value)) throw new Error('상태 값은 유한한 숫자여야 합니다.');
+ values.set(entry.name, value);
+ }
+ for (const state of program.states)
+ if (!values.has(state.name)) throw new Error(`저장된 상태가 없습니다: ${state.name}`);
+ return { source, draft, program, values: program.states.map(state => values.get(state.name)) };
+}
+
+export function parseProject(text) {
+ if (typeof text !== 'string' || encoder.encode(text).length > MAX_PROJECT_BYTES)
+ throw new Error('작업 파일이 너무 큽니다.');
+ let project;
+ try { project = JSON.parse(text); } catch { throw new Error('올바른 JSON 파일이 아닙니다.'); }
+ if (!project || typeof project !== 'object' || Array.isArray(project) || project.format !== 'pure-workbench')
+ throw new Error('Pure 작업물 형식이 아닙니다.');
+ if (project.version === 1) sourceText(project.source, '코드');
+ else if (project.version === 2) validateDocument(project);
+ else throw new Error('지원하지 않는 작업 파일 버전입니다.');
+ return project;
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/runtime.mjs b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/runtime.mjs
new file mode 100644
index 0000000..d8d6618
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/sources/prototypes/workbench/web/runtime.mjs
@@ -0,0 +1,350 @@
+import { compile } from './compiler.mjs';
+import { validateDocument } from './project.mjs';
+
+const messages = [
+ '', '실행기의 용량 한도를 넘었습니다.', '실행 정의가 유효하지 않습니다.',
+ '계산 스택의 범위를 벗어났습니다.', '0으로 나눌 수 없습니다.',
+ '계산 결과가 유한한 수의 범위를 벗어났습니다.', '조건 분기 범위가 유효하지 않습니다.',
+ '존재하지 않는 상태를 참조했습니다.', '시간 간격이 유효하지 않습니다.',
+ '정의되지 않은 입력 사건입니다.',
+];
+const sourceLimit = 32768;
+
+function problem(message, line = null, column = null) {
+ return Object.assign(new Error(message), { line, column });
+}
+
+function freezeProgram(value) {
+ if (value && typeof value === 'object') {
+ for (const child of Object.values(value)) freezeProgram(child);
+ Object.freeze(value);
+ }
+ return value;
+}
+
+export async function createRuntime(wasmBytes, evaluationOptions = {}) {
+ if (wasmBytes === undefined) {
+ const response = await fetch(new URL('./core.wasm', import.meta.url), { cache: 'no-store' });
+ if (!response.ok) throw new Error(`실행기를 불러오지 못했습니다 (HTTP ${response.status}).`);
+ wasmBytes = await response.arrayBuffer();
+ }
+ const module = await WebAssembly.compile(wasmBytes);
+ if (WebAssembly.Module.imports(module).length) throw new Error('이 실행기는 호스트 함수 없이 동작해야 합니다.');
+ const { exports: core } = await WebAssembly.instantiate(module, {});
+ if (typeof core.eval_bounded !== 'function' || typeof core.abort_program !== 'function' || typeof core.dispatch_point !== 'function' || typeof core.put_restored_value !== 'function' || typeof core.commit_restored_program !== 'function' || typeof core.bind_handler !== 'function' || typeof core.put_pointer_target !== 'function' || typeof core.bind_target_handler !== 'function' || typeof core.dispatch_target !== 'function' || typeof core.dispatch_value !== 'function')
+ throw new Error('실행기 버전이 맞지 않습니다. 새로고침하거나 core.wasm을 다시 빌드하세요.');
+ core.reset_all();
+ let program = null;
+ let appliedSource = '';
+ let lastEvent = null;
+ // Keep a failed event visible through its release/focus-loss cleanup.
+ // The active program can clear this diagnostic by apply or explicit reset.
+ let lastFailure = null;
+ const held = new Map();
+ const points = new Map();
+ let presenting = false;
+ let bindings = [];
+ let pointRoutes = new Map();
+ // One bounded publication buffer, never exposed to callers. No state mirror.
+ let displayValues = null, displayValid = null;
+ function available() {
+ if (presenting) throw new Error('출력 전달 중에는 실행기를 다시 호출할 수 없습니다.');
+ }
+ let evaluationPolicy = { cacheEntries: 0, historyEntries: 8, workLimit: 2048 };
+
+ function checked(code, line = null) {
+ if (code !== 0) throw problem(messages[code] || `실행기 오류 ${code}`, line);
+ }
+ function inputIndex(name) {
+ const index = program?.inputs.findIndex((input) => input.name === name) ?? -1;
+ if (index < 0) throw new Error(`정의되지 않은 입력: ${name}`);
+ return index;
+ }
+ function dispatch(event, name, phase, source, point = null, value = undefined) {
+ const status = value !== undefined ? core.dispatch_value(event, value) : point ? (point.route === undefined ? core.dispatch_point(event, point.x, point.y)
+ : core.dispatch_target(event, point.route, point.x, point.y)) : core.dispatch(event, event === 0 ? 1 / 60 : 0);
+ const pc = core.info(2) >>> 0;
+ lastEvent = { name, phase, source, status,
+ line: program?.instructions[pc]?.line ?? null, ops: core.info(3) >>> 0 };
+ if (point) { lastEvent.x = point.x; lastEvent.y = point.y; if (point.target) lastEvent.target = point.target; }
+ if (value !== undefined) lastEvent.value = value;
+ if (status) lastFailure = { ...lastEvent };
+ return status;
+ }
+
+ function evaluateDisplay() {
+ core.begin_evaluation(evaluationPolicy.workLimit);
+ if (!bindings.length) return null;
+ displayValues ??= new Float64Array(96);
+ displayValid ??= new Uint8Array(24);
+ let error = null, slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ displayValid[i] = 1;
+ for (const [name, binding] of bindings[i]) {
+ const value = core.eval_bounded(binding.start, binding.length);
+ if (core.evaluation_info(0) === 10) {
+ displayValid.fill(0);
+ return { code: 101, line: view.line,
+ message: '표시 계산의 작업량 한도를 넘었습니다. 한도를 늘리거나 표시식을 줄이세요.' };
+ }
+ if (!Number.isFinite(value) || ((name === 'width' || name === 'height' || name === 'radius') && value < 0)) {
+ error ??= { line: view.line, message: `${view.id}.${name}: 표시할 수 없는 값입니다. 0 나눗셈이나 음수 크기를 확인하세요.` };
+ displayValid[i] = 0;
+ }
+ displayValues[slot++] = value;
+ }
+ }
+ return error;
+ }
+
+ function status(viewError) {
+ const executionError = lastFailure?.status || 0;
+ return {
+ tick: core.info(0) >>> 0, revision: core.info(4) >>> 0,
+ displayError: viewError ? { code: viewError.code || 100, ...viewError } : null,
+ lastError: executionError || (viewError ? viewError.code || 100 : 0),
+ errorMessage: executionError ? messages[executionError] || `실행 오류 ${executionError}` : viewError?.message || '',
+ errorLine: executionError ? lastFailure.line : viewError?.line ?? null,
+ lastOps: core.info(3) >>> 0, successfulEvents: core.info(9) >>> 0,
+ held: [...held.keys()], lastEvent: lastEvent ? { ...lastEvent } : null,
+ lastFailure: lastFailure ? { ...lastFailure } : null,
+ memory: {
+ linearBytes: core.memory.buffer.byteLength,
+ reservedEngineBytes: core.layout(0), programReservedBytes: core.layout(1),
+ instructionBytes: core.layout(2), handlerBytes: core.layout(3),
+ activeIRBytes: core.layout(4), activeStateBytes: core.layout(5),
+ stagingReservedBytes: core.layout(6), evalStackBytes: core.layout(7),
+ pointerTargetBytes: core.layout(8), pointerTargets: core.layout(9),
+ },
+ };
+ }
+
+ function load(next, source, restored = null) {
+ const oldIds = new Map(restored ? [] : program?.states.map((state, index) => [state.name, index]) ?? []);
+ checked(core.begin_program(next.states.length, next.inputs.length));
+ try {
+ for (let index = 0; index < next.states.length; index++) {
+ const state = next.states[index];
+ checked(core.put_state(index, state.initial, oldIds.get(state.name) ?? -1), state.line);
+ if (restored) checked(core.put_restored_value(index, restored[index]), state.line);
+ }
+ for (const op of next.instructions) checked(core.put_instruction(op.op, op.arg, op.value), op.line);
+ for (const target of next.pointerTargets) checked(core.put_pointer_target(target.input, target.base, target.count));
+ for (const [index, handler] of next.handlers.entries()) {
+ checked(core.put_handler(handler.event, handler.start, handler.length), handler.line);
+ if (handler.parameterCount)
+ checked(handler.parameterBase === 255 ? core.bind_target_handler(index, handler.parameterCount)
+ : core.bind_handler(index, handler.parameterBase, handler.parameterCount), handler.line);
+ }
+ checked(restored ? core.commit_restored_program() : core.commit_program());
+ } catch (error) {
+ core.abort_program();
+ throw error;
+ }
+ pointRoutes = new Map(next.inputs.flatMap(input => (input.routes ?? []).map(route => [route.target, route])));
+ program = next;
+ bindings = next.views.map(view => Object.entries(view.bindings));
+ appliedSource = source;
+ lastEvent = null;
+ lastFailure = null;
+ }
+
+ const api = {
+ get currentProgram() { return program; },
+ configureEvaluation({ cacheEntries = evaluationPolicy.cacheEntries,
+ historyEntries = evaluationPolicy.historyEntries, workLimit = evaluationPolicy.workLimit } = {}) {
+ available();
+ for (const [name, value, maximum] of [['cacheEntries', cacheEntries, 32],
+ ['historyEntries', historyEntries, 8], ['workLimit', workLimit, 0xffffffff]]) {
+ if (!Number.isInteger(value) || value < 0 || value > maximum)
+ throw new Error(`${name}: 0~${maximum} 사이의 정수여야 합니다.`);
+ }
+ checked(core.configure_evaluation(cacheEntries, historyEntries));
+ evaluationPolicy = { cacheEntries, historyEntries, workLimit };
+ return { ...evaluationPolicy };
+ },
+ forgetEvaluation(part = 'all') {
+ available();
+ const flags = part === 'all' ? 3 : part === 'values' ? 1 : part === 'history' ? 2 : undefined;
+ if (flags === undefined) throw new Error('삭제할 기록은 values, history, all 중 하나여야 합니다.');
+ core.forget_evaluation(flags);
+ },
+ evaluationStats() {
+ return { ...evaluationPolicy, work: core.evaluation_info(1),
+ instructions: core.evaluation_info(2), cacheHits: core.evaluation_info(3),
+ reservedBytes: core.evaluation_info(6), dedicatedBytes: core.evaluation_info(7),
+ sharedBytes: core.evaluation_info(8), reuseAvailable: Boolean(core.evaluation_info(9)),
+ workspaceTagBytes: core.evaluation_info(10) };
+ },
+ apply(source) {
+ available();
+ if (typeof source !== 'string' || new TextEncoder().encode(source).length > sourceLimit) {
+ throw problem('정의는 UTF-8 기준 32,768바이트 이하의 텍스트여야 합니다.');
+ }
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 적용하세요. 현재 작업은 그대로 유지합니다.');
+ const next = freezeProgram(compile(source));
+ load(next, source);
+ return next;
+ },
+ restoreDocument(document) {
+ available();
+ if (held.size) throw problem('누르고 있는 입력을 놓은 뒤 복원하세요.');
+ const next = validateDocument(document);
+ load(freezeProgram(next.program), next.source, next.values);
+ return { source: next.source, draft: next.draft };
+ },
+ exportDocument(draft = appliedSource) {
+ available();
+ if (!program) throw problem('먼저 코드를 적용하세요.');
+ if (held.size) throw problem('조작을 끝낸 뒤 배치를 저장하세요.');
+ if (lastFailure) throw problem('실행 오류를 해결한 뒤 배치를 저장하세요.');
+ if (typeof draft !== 'string' || new TextEncoder().encode(draft).length > sourceLimit)
+ throw problem('편집 중인 코드는 UTF-8 32 KiB 이하여야 합니다.');
+ return { format: 'pure-workbench', version: 2, source: appliedSource, draft,
+ states: program.states.map((state, i) => {
+ const value = core.get_state(i);
+ return { name: state.name, value: Object.is(value, -0) ? '-0' : value };
+ }) };
+ },
+ reset() {
+ available();
+ held.clear();
+ points.clear();
+ core.reset_state();
+ lastEvent = null;
+ lastFailure = null;
+ },
+ frame(count = 1) {
+ available();
+ if (!Number.isInteger(count) || count < 0 || count > 600) throw new Error('프레임 수는 0~600 사이의 정수여야 합니다.');
+ if (!program) return 0;
+ for (let i = 0; i < count; i++) {
+ const code = dispatch(0, 'frame', 'frame', 'clock');
+ if (code !== 0) return code;
+ }
+ return 0;
+ },
+ down(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name) || new Set();
+ if (sources.has(source)) return 0;
+ const wasDown = sources.size > 0;
+ sources.add(source);
+ held.set(name, sources);
+ return wasDown ? 0 : dispatch(1 + index * 2, name, 'down', source);
+ },
+ up(name, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind === 'value') throw new Error('숫자 입력은 change(name, value)를 사용하세요.');
+ if (program.inputs[index].target || program.inputs[index].routes) throw new Error('좌표 입력은 point(name, phase, x, y)를 사용하세요.');
+ const sources = held.get(name);
+ if (!sources?.delete(source)) return 0;
+ if (sources.size) return 0;
+ held.delete(name);
+ return dispatch(2 + index * 2, name, 'up', source);
+ },
+ change(name, value, source = 'external') {
+ available();
+ const index = inputIndex(name);
+ if (program.inputs[index].kind !== 'value') throw new Error('숫자 값에 연결된 입력이 아닙니다.');
+ if (!Number.isFinite(value)) throw new Error('입력 값은 유한한 숫자여야 합니다.');
+ return dispatch(33 + index, name, 'change', source, null, value);
+ },
+ point(name, phase, x, y, source = 'external', target = undefined) {
+ available();
+ const index = inputIndex(name);
+ const input = program.inputs[index];
+ if (!input.target && !input.routes) throw new Error('포인터에 연결된 입력이 아닙니다.');
+ const route = input.routes ? pointRoutes.get(target) : undefined;
+ if (input.routes && (!route || program.pointerTargets[route.route].input !== index)) throw new Error('포인터 그룹에 연결된 도형 이름이 필요합니다.');
+ if (!input.routes && target !== undefined) throw new Error('단일 포인터 입력에는 대상 인자를 지정하지 않습니다.');
+ const owner = route ? `${name}:${target}` : name;
+ if (!['down', 'move', 'up', 'cancel'].includes(phase)) throw new Error('포인터 단계는 down, move, up, cancel 중 하나여야 합니다.');
+ if (!Number.isFinite(x) || !Number.isFinite(y)) throw new Error('포인터 좌표는 유한한 숫자여야 합니다.');
+ if (typeof source !== 'string' || source.length === 0) throw new Error('포인터 출처 이름이 필요합니다.');
+ let point = points.get(owner);
+ if (phase === 'down') {
+ if (point?.source === source) return 0;
+ if (point) throw new Error('이 입력은 다른 포인터가 사용 중입니다.');
+ point = {name, source, x, y, target, route:route?.route};
+ points.set(owner, point);
+ held.set(owner, new Set([source]));
+ } else {
+ if (!point || point.source !== source) return 0;
+ point.x = x; point.y = y;
+ if (phase === 'up' || phase === 'cancel') { points.delete(owner); held.delete(owner); }
+ }
+ const event = phase === 'move' ? 17 + index : phase === 'cancel' ? 25 + index : 1 + index * 2 + (phase === 'up' ? 1 : 0);
+ return dispatch(event, name, phase, source, point);
+ },
+ releaseAll() {
+ available();
+ let firstError = 0;
+ for (const point of [...points.values()]) {
+ const status = api.point(point.name, 'cancel', point.x, point.y, point.source, point.target);
+ if (!firstError) firstError = status;
+ }
+ for (const [name, sources] of [...held]) {
+ for (const source of [...sources]) {
+ const status = api.up(name, source);
+ if (!firstError) firstError = status;
+ }
+ }
+ return firstError;
+ },
+ exportProject() {
+ return { format: 'pure-workbench', version: 1, source: appliedSource };
+ },
+ // Synchronous trusted output adapter. Callbacks run only after the whole
+ // display has been evaluated. Runtime mutation/reentrant reads are refused.
+ // Exceptions from an adapter propagate; the next call republishes all values.
+ present(target) {
+ available();
+ presenting = true;
+ try {
+ const { begin, state, view, value, end } = target;
+ for (const callback of [begin, state, view, value, end])
+ if (typeof callback !== 'function') throw new TypeError('출력 어댑터 함수가 필요합니다.');
+ const error = evaluateDisplay();
+ begin.call(target, program);
+ for (let i = 0; i < (program?.states.length ?? 0); i++) state.call(target, i, core.get_state(i));
+ let slot = 0, visible = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const valid = Boolean(displayValid[i]);
+ view.call(target, i, valid);
+ for (const [name] of bindings[i]) {
+ if (valid) value.call(target, i, name, displayValues[slot]);
+ slot++;
+ }
+ if (valid) visible++;
+ }
+ end.call(target, visible);
+ return status(error);
+ } finally { presenting = false; }
+ },
+ snapshot() {
+ available();
+ const error = evaluateDisplay();
+ const states = Object.fromEntries((program?.states ?? []).map((state, index) => [state.name, core.get_state(index)]));
+ const views = [];
+ let slot = 0;
+ for (let i = 0; i < bindings.length; i++) {
+ const view = program.views[i];
+ const rendered = displayValid[i] ? { id: view.id, type: view.type, color: view.color, prefix: view.prefix } : null;
+ for (const [name] of bindings[i]) {
+ if (rendered) rendered[name] = displayValues[slot];
+ slot++;
+ }
+ if (rendered) views.push(rendered);
+ }
+ return { states, views, ...status(error) };
+ },
+ };
+ api.configureEvaluation(evaluationOptions);
+ return Object.freeze(api);
+}
diff --git a/prototypes/connections/results/2026-09-23-prepared-connections/verification.json b/prototypes/connections/results/2026-09-23-prepared-connections/verification.json
new file mode 100644
index 0000000..2c4036d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-23-prepared-connections/verification.json
@@ -0,0 +1,51 @@
+{
+ "date": "2026-09-23",
+ "scope": "Authored storage/response connections, prepared range semantics, lifetime correctness; no performance comparison",
+ "compiler": "cc (Debian 14.2.0-19) 14.2.0",
+ "os_page_size_bytes": 16384,
+ "cwd": "prototypes/connections",
+ "native_command": "make check EVIDENCE=results/2026-09-23-prepared-connections/native.json",
+ "sanitized_command": "make check BUILD=build/sanitized CFLAGS='-std=c17 -O1 -g -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -fno-omit-frame-pointer' EVIDENCE=results/2026-09-23-prepared-connections/sanitized.json",
+ "core_checks": {
+ "test-flow": {
+ "native": "passed",
+ "asan_ubsan": "passed"
+ },
+ "test-program": {
+ "native": "passed",
+ "asan_ubsan": "passed",
+ "boundary_semantic_comparisons": 3584
+ },
+ "leak_detection_disabled": false
+ },
+ "unit_binary_sha256": {
+ "build/test-flow": "63830f166dc326d95e91a30b24bba1f750de05c50b60cf454616b35eef1634dc",
+ "build/test-program": "cb8e9de15301090fda719144bd0fbbbeb9e6e91a14b2bae8e434df2ac510b527",
+ "build/sanitized/test-flow": "1b608d5ad31b21180e8a4bce0c0ceee79db281c93ef2e7adf0261ca0b5f96df2",
+ "build/sanitized/test-program": "4396abe70699580d8c27d74aeb50713a9452e6f4060289b97e2d48d5c478666d"
+ },
+ "integration_scenarios_each": 22,
+ "original_storage_scenarios": 16,
+ "authored_connection_scenarios": 6,
+ "source_snapshots": "sources/",
+ "source_hashes_equal": true,
+ "source_snapshots_match_records": true,
+ "final_binaries_match_records": true,
+ "prepared_connections_equal": true,
+ "native_dynamic_dependencies_ldd": [
+ "\tlinux-vdso.so.1 (0x00007ffee8528000)",
+ "\tlibc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x00007ffee82e0000)",
+ "\t/lib/ld-linux-aarch64.so.1 (0x00007ffee84f0000)"
+ ],
+ "limitations": [
+ "Fixed byte-range authoring profile, not the general application language or graph runtime",
+ "One registered storage effect per handler; constant ranges, no dynamic branches or feedback loops",
+ "The native connection authoring parser is separate from the existing UI/scalar parser",
+ "runtime_view_steps is a structural description, not a measured instruction count",
+ "Logical payload bounds exclude mmap page rounding, page cache, disk retention, sockets and client allocations",
+ "Selecting input bytes for a reply retains and charges the complete original receive allocation",
+ "Synchronous storage calls delay other connections and timeout enforcement",
+ "Linux AArch64 only; macOS and real power loss have not been tested",
+ "Unpublished files left by crashes have no automatic recovery/collection policy"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-async-effects/async-core.json b/prototypes/connections/results/2026-09-24-async-effects/async-core.json
new file mode 100644
index 0000000..d0932f0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-effects/async-core.json
@@ -0,0 +1,55 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "selected-owner-thread-async-effects",
+ "max_text_bytes": 8192,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "effect_bytes": 128
+ },
+ "archive_members": [
+ "runtime-async.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Selected owner-thread completion extension. Host I/O and worker stacks are excluded. The default execution core and fixed document packages do not link this profile."
+ },
+ "layout": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8,
+ "effect_bytes": 128
+ },
+ "sections": {
+ "text": 7312,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime-async.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 6392\t 0\t 0\t 6392\t 18f8\truntime-async.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution-async.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution-async.a)\n",
+ "archive_sha256": "afa5efe941031832232aec8a64e0727b93927995edd1d395f8feeb7fa4f9611d",
+ "layout_binary_sha256": "71866a57a3a2af37a8e3d4f2f97669c482b11b3a408a1d918e5de068dab9e34a",
+ "budget_sha256": "496e34596e24418efb46e460126b7d67492137207be988525abda1397d70c539",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-async-effects/default-core.json b/prototypes/connections/results/2026-09-24-async-effects/default-core.json
new file mode 100644
index 0000000..b92c015
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-effects/default-core.json
@@ -0,0 +1,53 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Release object sections and C bookkeeping, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 5932,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 5012\t 0\t 0\t 5012\t 1394\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "2de4e84fe2c104368339145ffa7ade5c31a9fd0e2a4ff00ff5edd469759b3c79",
+ "layout_binary_sha256": "db112a9cfd8deed80b9bfbff7628958fdb290cadab1efc7223d8d15ef4c4c389",
+ "budget_sha256": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-async-effects/flow.json b/prototypes/connections/results/2026-09-24-async-effects/flow.json
new file mode 100644
index 0000000..75447c2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-effects/flow.json
@@ -0,0 +1 @@
+{"async_effects":"authored-document-worker-overlap-release-forward-budget-recovery"}
diff --git a/prototypes/connections/results/2026-09-24-async-effects/sanitized.json b/prototypes/connections/results/2026-09-24-async-effects/sanitized.json
new file mode 100644
index 0000000..75447c2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-effects/sanitized.json
@@ -0,0 +1 @@
+{"async_effects":"authored-document-worker-overlap-release-forward-budget-recovery"}
diff --git a/prototypes/connections/results/2026-09-24-async-http/full-check.json b/prototypes/connections/results/2026-09-24-async-http/full-check.json
new file mode 100644
index 0000000..55e7539
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-http/full-check.json
@@ -0,0 +1,614 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 43224
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 43224
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "editor_sha256": "4b9f3e1882d010784d04673a231fdf3ec47b8823527e74f049d5ee3401e6fc60",
+ "binary_sha256": "08a8283c573fd6512b13242ec8a97286be913db6843ccf971a0fe01dd93eb989",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store.c": "44702e9414c26d1ee336b2e36e6713560013c2c8d0091a8900042e2468f88015",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "e8c84d688ba078e909c57d56c882c963ad5431afe10051bdec84486d3e155b54",
+ "prototypes/connections/runtime.h": "2a9d00a7f6f916041380cef3e3dc30602364b05288f62607b62b3de2be2595d1",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "58526592ee906833718101f1d33878d66c5e357097d5347d02755d922c36dda9",
+ "prototypes/connections/server.c": "acab2509cbde4431a2e0d9e18ad0e917f8f827b7eab46acb3d81afef442b3655",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "f39a7c411afa80812aec6e7a7250cdc833e97cffef8d0cce25d960fe435784f6",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "31933e9d35521d2e9ae0efb1ff21fb4c9a3ab0e3e02444556ebb6db183155b0d",
+ "prototypes/connections/core-layout.c": "e3123bdf74edb99556b05d7cd3a36b6119ec30829541b0ddba2e23e5900b089d",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-async-http/gated.json b/prototypes/connections/results/2026-09-24-async-http/gated.json
new file mode 100644
index 0000000..a4dd464
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-http/gated.json
@@ -0,0 +1,38 @@
+{
+ "async_http": "reactor-progress-deadline-recovery-draining-shutdown",
+ "deadline_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 13,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 1,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 10,
+ "server_structure_bytes": 43224
+ },
+ "shutdown_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 13,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 5,
+ "server_structure_bytes": 43224
+ },
+ "gated_test_binary_sha256": "aaa9c62fbc1533444467d61ad9a5fe3443b4e37939a3a6aa23301f5e19f5f7b1"
+}
diff --git a/prototypes/connections/results/2026-09-24-async-http/profile.json b/prototypes/connections/results/2026-09-24-async-http/profile.json
new file mode 100644
index 0000000..6599363
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-http/profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-one-worker-document-http",
+ "scope": "Optional one-worker HTTP host on the recorded Linux AArch64/GCC 14 toolchain. Section limits exclude the 128 KiB worker stack, libc, heap, mapped files and kernel buffers. Default CLI and HTTP do not link this option. Inspect process RSS and VM separately.",
+ "budget_sha256": "4c851b44ad47629459b78de3bdc8ba984f45cc799c7d4933d3edbcbaa12f21e8",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-connections-async": {
+ "sections": {
+ "text": 47897,
+ "data": 1180,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "08a8283c573fd6512b13242ec8a97286be913db6843ccf971a0fe01dd93eb989"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-async-http/sanitized.json b/prototypes/connections/results/2026-09-24-async-http/sanitized.json
new file mode 100644
index 0000000..5dc5c69
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-http/sanitized.json
@@ -0,0 +1,38 @@
+{
+ "async_http": "reactor-progress-deadline-recovery-draining-shutdown",
+ "deadline_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 13,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 1,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 10,
+ "server_structure_bytes": 43224
+ },
+ "shutdown_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 13,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 5,
+ "server_structure_bytes": 43224
+ },
+ "gated_test_binary_sha256": "f2d3e9abaaa2a389baff6c5bcfdb760ede69ff7e05aea479192b4f0c94ab05cf"
+}
diff --git a/prototypes/connections/results/2026-09-24-async-http/service-scale-memory.json b/prototypes/connections/results/2026-09-24-async-http/service-scale-memory.json
new file mode 100644
index 0000000..5507b88
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-http/service-scale-memory.json
@@ -0,0 +1,100 @@
+{
+ "profile": "document-app-many-objects-concurrent-clients",
+ "documents_per_variant": 1024,
+ "clients": 8,
+ "body_bytes": 8192,
+ "operations_per_variant": 4096,
+ "server_budget_bytes": 1048576,
+ "peak_rss_limit_kib": 4096,
+ "same_final_documents": "pass",
+ "fixed": {
+ "binary_sha256": "584b85fce5833d6a1eb5919a6f79c0648200e4ab3f65f2e90d008ea88db3be51",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1504,
+ "peak_rss_kib": 1696,
+ "idle_vm_kib": 2448,
+ "peak_vm_kib": 2512,
+ "idle_threads": 1,
+ "peak_threads": 1,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49184,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 449903,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 40848
+ }
+ },
+ "source": {
+ "binary_sha256": "f49ad1538f8ebeecc65511db052a7610c966d33992c5eb076bd36124680aebd1",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1536,
+ "peak_rss_kib": 1712,
+ "idle_vm_kib": 2464,
+ "peak_vm_kib": 2528,
+ "idle_threads": 1,
+ "peak_threads": 1,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 41001,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 481696,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 41528
+ }
+ },
+ "source_async": {
+ "binary_sha256": "08a8283c573fd6512b13242ec8a97286be913db6843ccf971a0fe01dd93eb989",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1536,
+ "peak_rss_kib": 1712,
+ "idle_vm_kib": 2656,
+ "peak_vm_kib": 2736,
+ "idle_threads": 2,
+ "peak_threads": 2,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 57368,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 226974,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 43224
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-async-read-write/full-check.json b/prototypes/connections/results/2026-09-24-async-read-write/full-check.json
new file mode 100644
index 0000000..914e9cd
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-read-write/full-check.json
@@ -0,0 +1,614 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 11,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115421,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 54,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 9,
+ "borrowed_output_bytes": 1,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 1,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 16,
+ "borrowed_output_bytes": 113,
+ "server_structure_bytes": 43320
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 43320
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "editor_sha256": "4b9f3e1882d010784d04673a231fdf3ec47b8823527e74f049d5ee3401e6fc60",
+ "binary_sha256": "63211eebd1952dbc9f31bc2eee76c1c661df9bce14e3932b4e15e52fdae5d763",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store.c": "44702e9414c26d1ee336b2e36e6713560013c2c8d0091a8900042e2468f88015",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "e8c84d688ba078e909c57d56c882c963ad5431afe10051bdec84486d3e155b54",
+ "prototypes/connections/runtime.h": "2a9d00a7f6f916041380cef3e3dc30602364b05288f62607b62b3de2be2595d1",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "58526592ee906833718101f1d33878d66c5e357097d5347d02755d922c36dda9",
+ "prototypes/connections/server.c": "e8632667de6feaf4d495f87abb159775650e3e4eaf6713b9dfdc5f82807c2bf9",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "f39a7c411afa80812aec6e7a7250cdc833e97cffef8d0cce25d960fe435784f6",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "f9a0c9fa7d0f40d6d72bc72a429dd36e136e27207aa6b0c01df9505d82189b6d",
+ "prototypes/connections/core-layout.c": "e3123bdf74edb99556b05d7cd3a36b6119ec30829541b0ddba2e23e5900b089d",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-async-read-write/gated.json b/prototypes/connections/results/2026-09-24-async-read-write/gated.json
new file mode 100644
index 0000000..04d5e53
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-read-write/gated.json
@@ -0,0 +1,53 @@
+{
+ "async_http": "snapshot-read-write-overlap-deadline-recovery-draining-shutdown",
+ "before_publication": {
+ "status": 200,
+ "etag": "\"1\"",
+ "body": "old"
+ },
+ "after_publication": {
+ "status": 200,
+ "etag": "\"2\"",
+ "body": "oldafter"
+ },
+ "shutdown_restore": {
+ "revision": "2",
+ "body": "oldafter"
+ },
+ "deadline_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 1,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 43320
+ },
+ "shutdown_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 13,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 5,
+ "server_structure_bytes": 43320
+ },
+ "test_source_sha256": "f38c9d3d784676ce815c276fbffc10e00f767aaa803793d8db311c19ef3b9085",
+ "gated_test_binary_sha256": "e1764fd031a24851d3fab665df1538fa947e2bf653accaa528bb60cd6daf7105"
+}
diff --git a/prototypes/connections/results/2026-09-24-async-read-write/profile.json b/prototypes/connections/results/2026-09-24-async-read-write/profile.json
new file mode 100644
index 0000000..dee3dc7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-read-write/profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-read-write-document-http",
+ "scope": "Optional one-read/one-write-worker HTTP host on the recorded Linux AArch64/GCC 14 toolchain. Section limits exclude the two 128 KiB worker stacks, libc, heap, mapped files and kernel buffers. Default CLI and HTTP do not link this option. Inspect process RSS and VM separately.",
+ "budget_sha256": "acd82386572fc2f874ca2fee5f4eed68ee145cf990d7315a9f1aff06daf51995",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-connections-async": {
+ "sections": {
+ "text": 48401,
+ "data": 1180,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "63211eebd1952dbc9f31bc2eee76c1c661df9bce14e3932b4e15e52fdae5d763"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-async-read-write/sanitized.json b/prototypes/connections/results/2026-09-24-async-read-write/sanitized.json
new file mode 100644
index 0000000..f867695
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-read-write/sanitized.json
@@ -0,0 +1,53 @@
+{
+ "async_http": "snapshot-read-write-overlap-deadline-recovery-draining-shutdown",
+ "before_publication": {
+ "status": 200,
+ "etag": "\"1\"",
+ "body": "old"
+ },
+ "after_publication": {
+ "status": 200,
+ "etag": "\"2\"",
+ "body": "oldafter"
+ },
+ "shutdown_restore": {
+ "revision": "2",
+ "body": "oldafter"
+ },
+ "deadline_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 1,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 43320
+ },
+ "shutdown_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 13,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 5,
+ "server_structure_bytes": 43320
+ },
+ "test_source_sha256": "f38c9d3d784676ce815c276fbffc10e00f767aaa803793d8db311c19ef3b9085",
+ "gated_test_binary_sha256": "b3b89925aabe1f6edd3a782d99c5adb1dff68bf727066fb00372a16d00d92e53"
+}
diff --git a/prototypes/connections/results/2026-09-24-async-read-write/service-scale.json b/prototypes/connections/results/2026-09-24-async-read-write/service-scale.json
new file mode 100644
index 0000000..eb73971
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-async-read-write/service-scale.json
@@ -0,0 +1,100 @@
+{
+ "profile": "document-app-many-objects-concurrent-clients",
+ "documents_per_variant": 1024,
+ "clients": 8,
+ "body_bytes": 8192,
+ "operations_per_variant": 4096,
+ "server_budget_bytes": 1048576,
+ "peak_rss_limit_kib": 4096,
+ "same_final_documents": "pass",
+ "fixed": {
+ "binary_sha256": "a16cc0c8790cfc6745c6d78f09f527dcd5d9e749669fe4ad9b0d817f83f6cfee",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1504,
+ "peak_rss_kib": 1680,
+ "idle_vm_kib": 2448,
+ "peak_vm_kib": 2528,
+ "idle_threads": 1,
+ "peak_threads": 1,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49201,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 899599,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 40848
+ }
+ },
+ "source": {
+ "binary_sha256": "64959669514855565554abb4622dc2bee34a0792485f19bd6466eb63a68e9688",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1520,
+ "peak_rss_kib": 1696,
+ "idle_vm_kib": 2464,
+ "peak_vm_kib": 2528,
+ "idle_threads": 1,
+ "peak_threads": 1,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49201,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 465705,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 41528
+ }
+ },
+ "source_async": {
+ "binary_sha256": "63211eebd1952dbc9f31bc2eee76c1c661df9bce14e3932b4e15e52fdae5d763",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1552,
+ "peak_rss_kib": 1728,
+ "idle_vm_kib": 2848,
+ "peak_vm_kib": 2928,
+ "idle_threads": 3,
+ "peak_threads": 3,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49192,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 238875,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 43320
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/policy-peer.json b/prototypes/connections/results/2026-09-24-atomic-policy/policy-peer.json
new file mode 100644
index 0000000..e93d7b0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/policy-peer.json
@@ -0,0 +1,12 @@
+{
+ "checks": [
+ "authored final size is checked against the locked document version",
+ "a rejected growth leaves revision and bytes unchanged",
+ "stale revision reports conflict before the policy decision",
+ "source CLI and HTTP share a policy and committed document",
+ "source policy changes behavior after the HTTP host restarts",
+ "fixed CLI and HTTP retain their compiled policy after source edits",
+ "source and fixed terminal editors preserve unsaved drafts on policy denial",
+ "authenticated peer shares the policy and current stored version"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/policy.json b/prototypes/connections/results/2026-09-24-atomic-policy/policy.json
new file mode 100644
index 0000000..4e85685
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/policy.json
@@ -0,0 +1,11 @@
+{
+ "checks": [
+ "authored final size is checked against the locked document version",
+ "a rejected growth leaves revision and bytes unchanged",
+ "stale revision reports conflict before the policy decision",
+ "source CLI and HTTP share a policy and committed document",
+ "source policy changes behavior after the HTTP host restarts",
+ "fixed CLI and HTTP retain their compiled policy after source edits",
+ "source and fixed terminal editors preserve unsaved drafts on policy denial"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-linux-aarch64.tar.gz
new file mode 100644
index 0000000..6383ee8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-linux-aarch64.tar.gz.check.json b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-linux-aarch64.tar.gz.check.json
new file mode 100644
index 0000000..a9977dd
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-linux-aarch64.tar.gz.check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "c82d4815c55e44d1293204d3151aea16fd1c2a439e342337a7a04ef191787bb6",
+ "archive_bytes": 12966,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..013ccec
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-tui-linux-aarch64.tar.gz.check.json b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-tui-linux-aarch64.tar.gz.check.json
new file mode 100644
index 0000000..98c8fec
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-fixed-cli-tui-linux-aarch64.tar.gz.check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "9dee9779e621d46c6099367cdca8dc65942cf7eb32480a06b79e577be8f7e1a9",
+ "archive_bytes": 32144,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-linux-aarch64.tar.gz
new file mode 100644
index 0000000..b82c68c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-linux-aarch64.tar.gz.check.json b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-linux-aarch64.tar.gz.check.json
new file mode 100644
index 0000000..bb760ea
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-linux-aarch64.tar.gz.check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "3056f56b80c89e9b92755b36f4ea22a579c336ab48a32a22b9fa619eef810dd0",
+ "archive_bytes": 22862,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..73fdfe3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-tui-linux-aarch64.tar.gz.check.json b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-tui-linux-aarch64.tar.gz.check.json
new file mode 100644
index 0000000..6b54198
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-document-source-cli-tui-linux-aarch64.tar.gz.check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "308766d5f31ac289ce65f0af849add3564d90a3c42148b46bc6a1db02e64a564",
+ "archive_bytes": 51398,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-tui"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "relocated source-loaded TUI and CLI share UTF-8, large and many-document paths"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-atomic-policy/pure-source-preview.tar.gz
new file mode 100644
index 0000000..0da15d4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-atomic-policy/source-package-check.json b/prototypes/connections/results/2026-09-24-atomic-policy/source-package-check.json
new file mode 100644
index 0000000..71cd254
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-atomic-policy/source-package-check.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "e68c5336dd0d4c20b5f6eed2d3fc132cec64419498fc8028b065774770f8f47c",
+ "archive_bytes": 337937,
+ "source_files": 173,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean native TLS client and both server profiles pass authenticated document work",
+ "clean selected page store exports mixed revisions to the default flat store",
+ "clean one-MiB document fans out to two same-process Pure domains with independent conflict and release",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/cli-check.json b/prototypes/connections/results/2026-09-24-compact-runtime/cli-check.json
new file mode 100644
index 0000000..3e93243
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/cli-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "c69d3934b3567338c5a9c607b2a7f5df19963f3b45d6172d5538e8444125437b",
+ "archive_bytes": 12885,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/cli-tui-check.json b/prototypes/connections/results/2026-09-24-compact-runtime/cli-tui-check.json
new file mode 100644
index 0000000..5d70484
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/cli-tui-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "5d554fc24ce273306efe77be9e137424cac08f16c067f4691206a33030af844b",
+ "archive_bytes": 31971,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/cli-tui.tar.gz b/prototypes/connections/results/2026-09-24-compact-runtime/cli-tui.tar.gz
new file mode 100644
index 0000000..1846344
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/cli-tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/cli.tar.gz b/prototypes/connections/results/2026-09-24-compact-runtime/cli.tar.gz
new file mode 100644
index 0000000..b216469
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/cli.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/core.json b/prototypes/connections/results/2026-09-24-compact-runtime/core.json
new file mode 100644
index 0000000..63eb227
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/core.json
@@ -0,0 +1,53 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Compact release object sections and C bookkeeping, without opt-in PURE_RUNTIME_METRICS, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 5908,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 4988\t 0\t 0\t 4988\t 137c\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "bb5750a47f6f8ac4307dd633d836460d6045347880a6c53df9669e675e49929e",
+ "layout_binary_sha256": "04c008fb7e0b1ecc8435bce6fbc4478de6180a54da6538d8742acb9b51992fe3",
+ "budget_sha256": "e418419db6231305342ea8780149948e0e41e28b3afb937268e80b4695d3d5cd",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/default-profile.json b/prototypes/connections/results/2026-09-24-compact-runtime/default-profile.json
new file mode 100644
index 0000000..b12bfac
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/default-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35783,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "e1d49cb048b3e9c25183ab0a4cf30c55486f696c13d20a85d69e0ddc04e040c7"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 43938,
+ "data": 1068,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "662e2e9dfa6b77d06781d36912b9c2d79427a95e9ec14bc174454fb3f54deecb"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/fixed-memory.json b/prototypes/connections/results/2026-09-24-compact-runtime/fixed-memory.json
new file mode 100644
index 0000000..cddbe7b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/fixed-memory.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "fixed-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, the embedded prepared program, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1104,
+ "one_mib_edit_rss_kib": 2112,
+ "one_mib_show_rss_kib": 1072
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "df77304f4ab30eaee3ef41f8ac1f353d8faebcba163cfd76f0b18973e6dc16f5",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/fixed-profile.json b/prototypes/connections/results/2026-09-24-compact-runtime/fixed-profile.json
new file mode 100644
index 0000000..ff98463
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/fixed-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files.",
+ "budget_sha256": "2b7e550992abb1872e52846dec712fab59b78692b776fd7e648d7976299f4b2a",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19244,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "df77304f4ab30eaee3ef41f8ac1f353d8faebcba163cfd76f0b18973e6dc16f5"
+ },
+ "pure-connections-fixed": {
+ "sections": {
+ "text": 26549,
+ "data": 1028,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "9cc73e8f8da266083e8da0628bb30441f6fa9f73317d75e65df8b5231007c746"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/source-cli-check.json b/prototypes/connections/results/2026-09-24-compact-runtime/source-cli-check.json
new file mode 100644
index 0000000..78c01d5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/source-cli-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "0d2785a8893f7cb4b9947c64eb278587f96720926163575c3ec51e106fafedc7",
+ "archive_bytes": 22454,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/source-cli.tar.gz b/prototypes/connections/results/2026-09-24-compact-runtime/source-cli.tar.gz
new file mode 100644
index 0000000..cb6492f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/source-cli.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/tui-profile.json b/prototypes/connections/results/2026-09-24-compact-runtime/tui-profile.json
new file mode 100644
index 0000000..986fd17
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/tui-profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app, including the bounded document browser. The raised text ceiling reviews its measured 2,541-byte addition; default CLI and core ceilings are unchanged. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS, including 1,024-key browsing, is checked by check_tui.py on the recorded Linux AArch64 host.",
+ "budget_sha256": "4d3097c9ec3c0139cbdd82161a74d610c15d31c6ee5625101410627664f925e7",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "sections": {
+ "text": 32015,
+ "data": 1036,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "3118fa11fe6ee6587bb122ae30a0d3c5cf1a8cec3131bb65b11246480c9d3b9e"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-compact-runtime/tui.json b/prototypes/connections/results/2026-09-24-compact-runtime/tui.json
new file mode 100644
index 0000000..639ae64
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-compact-runtime/tui.json
@@ -0,0 +1,22 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1808,
+ "one_mib_peak_rss_kib": 3168,
+ "one_thousand_key_list_peak_rss_kib": 1888,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "3118fa11fe6ee6587bb122ae30a0d3c5cf1a8cec3131bb65b11246480c9d3b9e"
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range-source/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-copy-range-source/pure-source-preview.tar.gz
new file mode 100644
index 0000000..b0a8e7a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range-source/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-copy-range-source/source-check-linux-aarch64.json b/prototypes/connections/results/2026-09-24-copy-range-source/source-check-linux-aarch64.json
new file mode 100644
index 0000000..aad35c2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range-source/source-check-linux-aarch64.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "ce48ef8e330cff470b78aec9c9e6c6d8877e4c8c371512f190b91b6036ddc8ba",
+ "archive_bytes": 324261,
+ "source_files": 166,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17 build and host-neutral behavior tests pass",
+ "clean fixed and source-loaded native terminal PTY scenarios pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean native TLS client and both server profiles pass authenticated document work",
+ "clean selected Linux copy path passes app, scale, size, RSS and traced one-MiB splice",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/copy-path.json b/prototypes/connections/results/2026-09-24-copy-range/copy-path.json
new file mode 100644
index 0000000..5c714ed
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/copy-path.json
@@ -0,0 +1,27 @@
+{
+ "profile": "linux-immutable-one-mib-last-byte-splice",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "baseline": {
+ "binary_sha256": "23ebc0ce1df9c49216511bee658fd5b9e373509e296bd2c2f8e76e6d3081cded",
+ "result_sha256": "06cb5e32505f66804f6e8c79e3230105ca4769444e1389ee36f6f11fd61f2d3a",
+ "object_pread_calls": 257,
+ "copy_file_range_calls": 0,
+ "copy_file_range_bytes": 0,
+ "pending_write_calls": 258,
+ "pending_write_bytes": 1048600,
+ "one_mib_splice_peak_rss_kib": 1056
+ },
+ "candidate": {
+ "binary_sha256": "52c2b828b0cba3564a37e3874f60bec793d1dd7031aff77ba850cee7683977f9",
+ "result_sha256": "06cb5e32505f66804f6e8c79e3230105ca4769444e1389ee36f6f11fd61f2d3a",
+ "object_pread_calls": 1,
+ "copy_file_range_calls": 1,
+ "copy_file_range_bytes": 1048575,
+ "pending_write_calls": 2,
+ "pending_write_bytes": 25,
+ "one_mib_splice_peak_rss_kib": 1056
+ },
+ "filesystem": "ext4",
+ "scratch_parent": "/home/eunhhu/work/pure/prototypes/connections/build",
+ "scope": "Successful object-file syscalls and child peak RSS; excludes physical device writes, page cache and proof of lower latency."
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/default-core.json b/prototypes/connections/results/2026-09-24-copy-range/default-core.json
new file mode 100644
index 0000000..63eb227
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/default-core.json
@@ -0,0 +1,53 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Compact release object sections and C bookkeeping, without opt-in PURE_RUNTIME_METRICS, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 5908,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 4988\t 0\t 0\t 4988\t 137c\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "bb5750a47f6f8ac4307dd633d836460d6045347880a6c53df9669e675e49929e",
+ "layout_binary_sha256": "04c008fb7e0b1ecc8435bce6fbc4478de6180a54da6538d8742acb9b51992fe3",
+ "budget_sha256": "e418419db6231305342ea8780149948e0e41e28b3afb937268e80b4695d3d5cd",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/default-fixed-memory.json b/prototypes/connections/results/2026-09-24-copy-range/default-fixed-memory.json
new file mode 100644
index 0000000..6c6d1cd
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/default-fixed-memory.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "fixed-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, the embedded prepared program, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1104,
+ "one_mib_edit_rss_kib": 2128,
+ "one_mib_show_rss_kib": 1072
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "04974e2d3c4d7f5fb22aff67e7399aa2ebcbd85eb24da0c0e41f3ef047d5ddec",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/default-fixed-profile.json b/prototypes/connections/results/2026-09-24-copy-range/default-fixed-profile.json
new file mode 100644
index 0000000..297b9b1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/default-fixed-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files.",
+ "budget_sha256": "2b7e550992abb1872e52846dec712fab59b78692b776fd7e648d7976299f4b2a",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19244,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "04974e2d3c4d7f5fb22aff67e7399aa2ebcbd85eb24da0c0e41f3ef047d5ddec"
+ },
+ "pure-connections-fixed": {
+ "sections": {
+ "text": 26549,
+ "data": 1028,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "0f1c24533177357c49270c01070a7376345763393b3914276ca028e52e8589b9"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/default-functional.json b/prototypes/connections/results/2026-09-24-copy-range/default-functional.json
new file mode 100644
index 0000000..7e54edf
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/default-functional.json
@@ -0,0 +1,636 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 1,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 113,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true,
+ "idle_slot_binding": true
+ },
+ "execution_core_test_sha256": "1e483f9c0525862041e843bba153106d7819052a787b683440d0babee80f8975",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "35554177ec2109f6603d88dd4b4bdccc33497e9f229e486666f224db8e24de9b",
+ "editor_sha256": "23ebc0ce1df9c49216511bee658fd5b9e373509e296bd2c2f8e76e6d3081cded",
+ "binary_sha256": "6cce6c7c18d8a24059455a2f6d4aa19c98e503a5b2e7462e2c8d3940f23bd827",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store.c": "0d3df2df40fa9035cd98a1052d4c9fdad298475e9df5d49cfa7d475188fda072",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "7389c1343d6253344c57d4f12bd9c8c472ed5c11d386839a1a2e3ee19f5f66ca",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "1ced6734ee07f3688e5c9cc0a8af639da88a1741dc3e6f65ec109baa2d826e6f",
+ "prototypes/connections/runtime.h": "e217b7acd94f3572d2780be1d6b13c5d5556227bab93b4f773e7db8b0eee6856",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "8c275bf564a674f0f8232026d0d7612df48f10054af75a43af5ed0bce7653e24",
+ "prototypes/connections/server.c": "e8632667de6feaf4d495f87abb159775650e3e4eaf6713b9dfdc5f82807c2bf9",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "f39a7c411afa80812aec6e7a7250cdc833e97cffef8d0cce25d960fe435784f6",
+ "prototypes/connections/test-splice.c": "80a942fe7cc05533df346fe656c0a1f9bbbbb803d72415aa56110f089de18322",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "72d30528cb59a3a8ca8cf8cc414873fe0b26d6093cd8f06bfe9585235ba5befb",
+ "prototypes/connections/core-layout.c": "e3123bdf74edb99556b05d7cd3a36b6119ec30829541b0ddba2e23e5900b089d",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "e418419db6231305342ea8780149948e0e41e28b3afb937268e80b4695d3d5cd",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/default-memory.json b/prototypes/connections/results/2026-09-24-copy-range/default-memory.json
new file mode 100644
index 0000000..0ed783a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/default-memory.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "source-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1056,
+ "one_mib_edit_rss_kib": 2080,
+ "one_mib_show_rss_kib": 1056
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "23ebc0ce1df9c49216511bee658fd5b9e373509e296bd2c2f8e76e6d3081cded",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/default-profile.json b/prototypes/connections/results/2026-09-24-copy-range/default-profile.json
new file mode 100644
index 0000000..fa1c423
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/default-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35783,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "23ebc0ce1df9c49216511bee658fd5b9e373509e296bd2c2f8e76e6d3081cded"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 43938,
+ "data": 1068,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "6cce6c7c18d8a24059455a2f6d4aa19c98e503a5b2e7462e2c8d3940f23bd827"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/functional.json b/prototypes/connections/results/2026-09-24-copy-range/functional.json
new file mode 100644
index 0000000..e645c99
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/functional.json
@@ -0,0 +1,636 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 12,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 1,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 113,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true,
+ "idle_slot_binding": true
+ },
+ "execution_core_test_sha256": "74e4a101d4c44c9aa6b544d6370cee570870386fb15c7444f6f077b2d975af8c",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "893349eba46c9e555ce8452296d4f776020d14310fcd7a55a6e78e1ba4b592fe",
+ "editor_sha256": "52c2b828b0cba3564a37e3874f60bec793d1dd7031aff77ba850cee7683977f9",
+ "binary_sha256": "34b501dec69c00aec2c5a4aaad2f6aca57de1b782f96d894a00536a440633c38",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store.c": "0d3df2df40fa9035cd98a1052d4c9fdad298475e9df5d49cfa7d475188fda072",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "7389c1343d6253344c57d4f12bd9c8c472ed5c11d386839a1a2e3ee19f5f66ca",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "1ced6734ee07f3688e5c9cc0a8af639da88a1741dc3e6f65ec109baa2d826e6f",
+ "prototypes/connections/runtime.h": "e217b7acd94f3572d2780be1d6b13c5d5556227bab93b4f773e7db8b0eee6856",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "8c275bf564a674f0f8232026d0d7612df48f10054af75a43af5ed0bce7653e24",
+ "prototypes/connections/server.c": "e8632667de6feaf4d495f87abb159775650e3e4eaf6713b9dfdc5f82807c2bf9",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "f39a7c411afa80812aec6e7a7250cdc833e97cffef8d0cce25d960fe435784f6",
+ "prototypes/connections/test-splice.c": "80a942fe7cc05533df346fe656c0a1f9bbbbb803d72415aa56110f089de18322",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "d4f130cc782730bc712268bbf4f0426bdf138ca03696fa7a32d781efded4f5cb",
+ "prototypes/connections/core-layout.c": "e3123bdf74edb99556b05d7cd3a36b6119ec30829541b0ddba2e23e5900b089d",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "e418419db6231305342ea8780149948e0e41e28b3afb937268e80b4695d3d5cd",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/memory.json b/prototypes/connections/results/2026-09-24-copy-range/memory.json
new file mode 100644
index 0000000..a1bb66d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/memory.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "source-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1056,
+ "one_mib_edit_rss_kib": 2080,
+ "one_mib_show_rss_kib": 1056
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "52c2b828b0cba3564a37e3874f60bec793d1dd7031aff77ba850cee7683977f9",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/profile.json b/prototypes/connections/results/2026-09-24-copy-range/profile.json
new file mode 100644
index 0000000..9975cfa
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 36052,
+ "data": 952,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "52c2b828b0cba3564a37e3874f60bec793d1dd7031aff77ba850cee7683977f9"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 44207,
+ "data": 1076,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "34b501dec69c00aec2c5a4aaad2f6aca57de1b782f96d894a00536a440633c38"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-copy-range/service-scale.json b/prototypes/connections/results/2026-09-24-copy-range/service-scale.json
new file mode 100644
index 0000000..6ff4bbb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-copy-range/service-scale.json
@@ -0,0 +1,70 @@
+{
+ "profile": "document-app-many-objects-concurrent-clients",
+ "documents_per_variant": 1024,
+ "clients": 8,
+ "body_bytes": 8192,
+ "operations_per_variant": 4096,
+ "server_budget_bytes": 1048576,
+ "peak_rss_limit_kib": 4096,
+ "same_final_documents": "pass",
+ "fixed": {
+ "binary_sha256": "2ca0c718fb8b38bd2bb6be2a1296c5346a427ca2fa8cf12607d81f81217f085b",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1504,
+ "peak_rss_kib": 1664,
+ "idle_vm_kib": 2448,
+ "peak_vm_kib": 2512,
+ "idle_threads": 1,
+ "peak_threads": 1,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49185,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 545480,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 40848
+ }
+ },
+ "source": {
+ "binary_sha256": "34b501dec69c00aec2c5a4aaad2f6aca57de1b782f96d894a00536a440633c38",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1552,
+ "peak_rss_kib": 1712,
+ "idle_vm_kib": 2464,
+ "peak_vm_kib": 2544,
+ "idle_threads": 1,
+ "peak_threads": 1,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 40992,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 326641,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 41528
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-document-peer/clean-peer.log b/prototypes/connections/results/2026-09-24-document-peer/clean-peer.log
new file mode 100644
index 0000000..ff472a7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/clean-peer.log
@@ -0,0 +1,43 @@
+make: Entering directory '/home/eunhhu/work/pure/prototypes/connections'
+python3 check_profile.py --build build/checkpoint-clean --budget peer-budget.json
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-document-peer",
+ "scope": "Review threshold for the explicitly selected authenticated document host on Linux AArch64/GCC 14. Includes linked application code but excludes the shared OpenSSL/libc implementations, process heap, stack, mappings and kernel buffers. Check measured whole-process RSS separately.",
+ "budget_sha256": "defe8efb4d544cdbf615de4d43d4ceba78fc7f1d958f245731202625052eb2ff",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-document-peer": {
+ "sections": {
+ "text": 46878,
+ "data": 1384,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6",
+ "libcrypto.so.3",
+ "libssl.so.3"
+ ],
+ "sha256": "e0bec4f698ce6b561a6caa8464636317409011e3101c48649cf5585c33ec9d31"
+ }
+ }
+}
+python3 check_document_peer.py --peer build/checkpoint-clean/pure-document-peer --editor build/checkpoint-clean/pure-edit
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 7840,
+ "server_after_large_work_rss_kib": 9488
+}
+make: Leaving directory '/home/eunhhu/work/pure/prototypes/connections'
diff --git a/prototypes/connections/results/2026-09-24-document-peer/clean-release.log b/prototypes/connections/results/2026-09-24-document-peer/clean-release.log
new file mode 100644
index 0000000..db3d23d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/clean-release.log
@@ -0,0 +1,737 @@
+make: Entering directory '/home/eunhhu/work/pure/prototypes/connections'
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror core-layout.c -o build/checkpoint-clean/core-layout
+python3 check_core.py --archive build/checkpoint-clean/libpure-execution.a --layout build/checkpoint-clean/core-layout
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Release object sections and C bookkeeping, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 5932,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 5012\t 0\t 0\t 5012\t 1394\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/checkpoint-clean/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/checkpoint-clean/libpure-execution.a)\n",
+ "archive_sha256": "d56c50e38c6c0949cfad069d34568da2ac45b1d60097cf9e7c4bf804f44c8128",
+ "layout_binary_sha256": "47cf1803007fc1ec85f119bd46195ad39d9f01ef0146bf5cc45e1af31eb18098",
+ "budget_sha256": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
+python3 check_profile.py --build build/checkpoint-clean
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35807,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 42761,
+ "data": 1040,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f"
+ }
+ }
+}
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror -DPURE_STORE_TEST test-flow.c store.c flow.c -o build/checkpoint-clean/test-flow
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror test-program.c program.c evaluate.c -o build/checkpoint-clean/test-program
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror test-fields.c program.c evaluate.c -o build/checkpoint-clean/test-fields
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror test-runtime.c program.c runtime.c evaluate.c store.c store-port.c -o build/checkpoint-clean/test-runtime
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror -DPURE_STORE_TEST test-splice.c program.c runtime.c evaluate.c store.c store-port.c -o build/checkpoint-clean/test-splice
+build/checkpoint-clean/test-flow
+{"transfer":"partial-consumption-and-single-release","storage":"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty"}
+build/checkpoint-clean/test-program
+{"program":"prepare-views-preserve-guards-types-effects-and-atomic-install","boundary_semantic_comparisons":3584}
+build/checkpoint-clean/test-fields
+{"fields":"named-layouts-unaligned-u32le-tail-dynamic-ranges-aliases-failures-limits","data_boundary_cases":48}
+python3 check.py --server build/checkpoint-clean/pure-connections --runtime-test build/checkpoint-clean/test-runtime --splice-test build/checkpoint-clean/test-splice --editor build/checkpoint-clean/pure-edit
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 31,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 1,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 113,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "07c328c98769d02d544aea2fc5389048a7620c00d9b3ea49b9c7ba45e33984b1",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "0e4ec2c78334af2056af376a6ba9aef7416a34c6d4fbd9082f4abb640e6de28c",
+ "editor_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03",
+ "binary_sha256": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "44702e9414c26d1ee336b2e36e6713560013c2c8d0091a8900042e2468f88015",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "5d08639b5a71572553bda47cbd35562805d601aaa81f20731cd9154768ec025e",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "e1735316769b4ce4d5904b9587ccfa3ebeafa26517c53dba4491191d58c97b8e",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "c0767afe55bdb13e1308414116047ad76d5b105c7b4162d7220c78c1d1a4076e",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
+make: Leaving directory '/home/eunhhu/work/pure/prototypes/connections'
diff --git a/prototypes/connections/results/2026-09-24-document-peer/dynamic.txt b/prototypes/connections/results/2026-09-24-document-peer/dynamic.txt
new file mode 100644
index 0000000..ff4f898
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/dynamic.txt
@@ -0,0 +1,31 @@
+
+Dynamic section at offset 0xfda8 contains 28 entries:
+ Tag Type Name/Value
+ 0x0000000000000001 (NEEDED) Shared library: [libssl.so.3]
+ 0x0000000000000001 (NEEDED) Shared library: [libcrypto.so.3]
+ 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
+ 0x000000000000000c (INIT) 0x1c18
+ 0x000000000000000d (FINI) 0x92f8
+ 0x0000000000000019 (INIT_ARRAY) 0x1fd98
+ 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
+ 0x000000000000001a (FINI_ARRAY) 0x1fda0
+ 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
+ 0x000000006ffffef5 (GNU_HASH) 0x2b0
+ 0x0000000000000005 (STRTAB) 0xc48
+ 0x0000000000000006 (SYMTAB) 0x2d0
+ 0x000000000000000a (STRSZ) 1217 (bytes)
+ 0x000000000000000b (SYMENT) 24 (bytes)
+ 0x0000000000000015 (DEBUG) 0x0
+ 0x0000000000000003 (PLTGOT) 0x1ffe8
+ 0x0000000000000002 (PLTRELSZ) 2256 (bytes)
+ 0x0000000000000014 (PLTREL) RELA
+ 0x0000000000000017 (JMPREL) 0x1348
+ 0x0000000000000007 (RELA) 0x1258
+ 0x0000000000000008 (RELASZ) 240 (bytes)
+ 0x0000000000000009 (RELAENT) 24 (bytes)
+ 0x000000006ffffffb (FLAGS_1) Flags: PIE
+ 0x000000006ffffffe (VERNEED) 0x11d8
+ 0x000000006fffffff (VERNEEDNUM) 3
+ 0x000000006ffffff0 (VERSYM) 0x110a
+ 0x000000006ffffff9 (RELACOUNT) 4
+ 0x0000000000000000 (NULL) 0x0
diff --git a/prototypes/connections/results/2026-09-24-document-peer/file-sizes.txt b/prototypes/connections/results/2026-09-24-document-peer/file-sizes.txt
new file mode 100644
index 0000000..c625025
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/file-sizes.txt
@@ -0,0 +1,2 @@
+68312 /tmp/pure-document-peer.stripped
+213080 prototypes/connections/build/pure-document-peer
diff --git a/prototypes/connections/results/2026-09-24-document-peer/hashes.txt b/prototypes/connections/results/2026-09-24-document-peer/hashes.txt
new file mode 100644
index 0000000..0546b43
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/hashes.txt
@@ -0,0 +1,4 @@
+7d6f7cac8422a800fa4407e76c29ce21aa0931020ee2f4aa7b0ae646b88aa034 prototypes/connections/document-peer.c
+df259073c5e1cd911495b48d4ccd43c8346d955a19a8773964abe58089fbebf9 prototypes/common/tls-link.c
+297a5d41b129ad134f5a398069565a1de0793024e6aa483def1dc1e09ebd1443 prototypes/common/tls-link.h
+e0bec4f698ce6b561a6caa8464636317409011e3101c48649cf5585c33ec9d31 prototypes/connections/build/pure-document-peer
diff --git a/prototypes/connections/results/2026-09-24-document-peer/package-check.json b/prototypes/connections/results/2026-09-24-document-peer/package-check.json
new file mode 100644
index 0000000..a6031fc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/package-check.json
@@ -0,0 +1,19 @@
+{
+ "archive_sha256": "dc3f7339bf5aa22b11eb5ac4c8b4a547168e0e06e65c8003a545f70a31500081",
+ "archive_bytes": 316927,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-connections",
+ "pure-document-peer",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted C/Python TLS peers share a 1 MiB document and recover",
+ "extracted GTK window, CLI and HTTP adapter edit the same document"
+ ],
+ "peer_idle_rss_kib": 7840,
+ "peer_after_large_work_rss_kib": 9488
+}
diff --git a/prototypes/connections/results/2026-09-24-document-peer/package-hashes.txt b/prototypes/connections/results/2026-09-24-document-peer/package-hashes.txt
new file mode 100644
index 0000000..825f3e9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/package-hashes.txt
@@ -0,0 +1,3 @@
+dc3f7339bf5aa22b11eb5ac4c8b4a547168e0e06e65c8003a545f70a31500081 dist/pure-document-linux-aarch64.tar.gz
+dc3f7339bf5aa22b11eb5ac4c8b4a547168e0e06e65c8003a545f70a31500081 /tmp/pure-document-repro.tar.gz
+dc3f7339bf5aa22b11eb5ac4c8b4a547168e0e06e65c8003a545f70a31500081 prototypes/connections/results/2026-09-24-document-peer/pure-document-linux-aarch64.tar.gz
diff --git a/prototypes/connections/results/2026-09-24-document-peer/peer-budget.json b/prototypes/connections/results/2026-09-24-document-peer/peer-budget.json
new file mode 100644
index 0000000..369a71c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/peer-budget.json
@@ -0,0 +1,23 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-document-peer",
+ "scope": "Review threshold for the explicitly selected authenticated document host on Linux AArch64/GCC 14. Includes linked application code but excludes the shared OpenSSL/libc implementations, process heap, stack, mappings and kernel buffers. Check measured whole-process RSS separately.",
+ "budget_sha256": "defe8efb4d544cdbf615de4d43d4ceba78fc7f1d958f245731202625052eb2ff",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-document-peer": {
+ "sections": {
+ "text": 46878,
+ "data": 1384,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6",
+ "libcrypto.so.3",
+ "libssl.so.3"
+ ],
+ "sha256": "e0bec4f698ce6b561a6caa8464636317409011e3101c48649cf5585c33ec9d31"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-document-peer/peer-flow.json b/prototypes/connections/results/2026-09-24-document-peer/peer-flow.json
new file mode 100644
index 0000000..32f3991
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/peer-flow.json
@@ -0,0 +1,16 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 7840,
+ "server_after_large_work_rss_kib": 9488
+}
diff --git a/prototypes/connections/results/2026-09-24-document-peer/peer-sanitized.json b/prototypes/connections/results/2026-09-24-document-peer/peer-sanitized.json
new file mode 100644
index 0000000..c1e698c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/peer-sanitized.json
@@ -0,0 +1,16 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 22592,
+ "server_after_large_work_rss_kib": 31632
+}
diff --git a/prototypes/connections/results/2026-09-24-document-peer/pure-document-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-document-peer/pure-document-linux-aarch64.tar.gz
new file mode 100644
index 0000000..006e71d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/pure-document-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-document-peer/scalar-refactor.json b/prototypes/connections/results/2026-09-24-document-peer/scalar-refactor.json
new file mode 100644
index 0000000..a1cf089
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/scalar-refactor.json
@@ -0,0 +1 @@
+{"alpn": "pass", "disconnect_release": "pass", "idle_deadline": "pass", "malformed_frames": "pass", "mutual_authentication": "pass", "persist_restart": "pass", "python_client": "pass", "revision_conflict": "pass", "server_connected_rss_kib": 8400, "server_hostname": "pass", "server_idle_rss_kib": 7824}
diff --git a/prototypes/connections/results/2026-09-24-document-peer/size.txt b/prototypes/connections/results/2026-09-24-document-peer/size.txt
new file mode 100644
index 0000000..a37699e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-document-peer/size.txt
@@ -0,0 +1,2 @@
+ text data bss dec hex filename
+ 46878 1384 16 48278 bc96 prototypes/connections/build/pure-document-peer
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/backpressure.json b/prototypes/connections/results/2026-09-24-fixed-http/backpressure.json
new file mode 100644
index 0000000..5723e36
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/backpressure.json
@@ -0,0 +1,61 @@
+{
+ "profile": "build-time-prepared-http-document-host",
+ "fixed_source_cli_same_document": "pass",
+ "conditional_conflict_and_invalid_splice": "pass",
+ "one_mib_roundtrip_and_native_edit": "pass",
+ "slow_consumer_budget_and_release": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 7,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097177,
+ "server_structure_bytes": 40848
+ },
+ "source_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 6,
+ "commits": 1,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 6,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097162,
+ "server_structure_bytes": 41528
+ },
+ "limited_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048586,
+ "server_structure_bytes": 40848
+ },
+ "fixed_sha256": "02acf468f18610332d3fe4b9c093b2bbff08496000dbae2b61151d7f3a7a46fa",
+ "source_sha256": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/final.json b/prototypes/connections/results/2026-09-24-fixed-http/final.json
new file mode 100644
index 0000000..1594bfa
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/final.json
@@ -0,0 +1,65 @@
+{
+ "profile": "build-time-prepared-http-document-host",
+ "fixed_source_cli_same_document": "pass",
+ "conditional_conflict_and_invalid_splice": "pass",
+ "one_mib_roundtrip_and_native_edit": "pass",
+ "slow_consumer_budget_and_release": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 7,
+ "ingress_prefix_copy_bytes": 3983,
+ "borrowed_output_bytes": 2097177,
+ "server_structure_bytes": 40848
+ },
+ "source_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 6,
+ "commits": 1,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 6,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097162,
+ "server_structure_bytes": 41528
+ },
+ "limited_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048586,
+ "server_structure_bytes": 40848
+ },
+ "fixed_idle_rss_kib": 1520,
+ "source_idle_rss_kib": 1568,
+ "fixed_after_large_rss_kib": 1648,
+ "source_after_large_rss_kib": 1696,
+ "fixed_sha256": "02acf468f18610332d3fe4b9c093b2bbff08496000dbae2b61151d7f3a7a46fa",
+ "source_sha256": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/fixed-profile.json b/prototypes/connections/results/2026-09-24-fixed-http/fixed-profile.json
new file mode 100644
index 0000000..3b3afbf
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/fixed-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files.",
+ "budget_sha256": "2b7e550992abb1872e52846dec712fab59b78692b776fd7e648d7976299f4b2a",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19244,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8"
+ },
+ "pure-connections-fixed": {
+ "sections": {
+ "text": 25228,
+ "data": 1000,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "02acf468f18610332d3fe4b9c093b2bbff08496000dbae2b61151d7f3a7a46fa"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/package.json b/prototypes/connections/results/2026-09-24-fixed-http/package.json
new file mode 100644
index 0000000..7bea960
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/package.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "dd1c29ca367271c5be88275695886e3d2b038b20565c016dc63bd761ed62c76e",
+ "archive_bytes": 31733,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/parity.json b/prototypes/connections/results/2026-09-24-fixed-http/parity.json
new file mode 100644
index 0000000..7566d43
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/parity.json
@@ -0,0 +1,43 @@
+{
+ "profile": "build-time-prepared-http-document-host",
+ "fixed_source_cli_same_document": "pass",
+ "conditional_conflict_and_invalid_splice": "pass",
+ "one_mib_roundtrip_and_native_edit": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 7,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097177,
+ "server_structure_bytes": 40848
+ },
+ "source_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 6,
+ "commits": 1,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 6,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097162,
+ "server_structure_bytes": 41528
+ },
+ "fixed_sha256": "02acf468f18610332d3fe4b9c093b2bbff08496000dbae2b61151d7f3a7a46fa",
+ "source_sha256": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/peak-memory.json b/prototypes/connections/results/2026-09-24-fixed-http/peak-memory.json
new file mode 100644
index 0000000..11902b5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/peak-memory.json
@@ -0,0 +1,67 @@
+{
+ "profile": "build-time-prepared-http-document-host",
+ "fixed_source_cli_same_document": "pass",
+ "conditional_conflict_and_invalid_splice": "pass",
+ "one_mib_roundtrip_and_native_edit": "pass",
+ "slow_consumer_budget_and_release": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 7,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097177,
+ "server_structure_bytes": 40848
+ },
+ "source_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 6,
+ "commits": 1,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 6,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097162,
+ "server_structure_bytes": 41528
+ },
+ "limited_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048586,
+ "server_structure_bytes": 40848
+ },
+ "fixed_idle_rss_kib": 1520,
+ "source_idle_rss_kib": 1552,
+ "fixed_after_large_rss_kib": 1648,
+ "source_after_large_rss_kib": 1680,
+ "fixed_peak_rss_kib": 2176,
+ "source_peak_rss_kib": 2096,
+ "fixed_sha256": "02acf468f18610332d3fe4b9c093b2bbff08496000dbae2b61151d7f3a7a46fa",
+ "source_sha256": "f39eaa24cad84a3ba34a5dd4b1c5bd6c23cdf18862ee3bb9bd6ba27cdba3f895"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/pure-document-fixed-http-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-fixed-http/pure-document-fixed-http-linux-aarch64.tar.gz
new file mode 100644
index 0000000..c53ece6
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/pure-document-fixed-http-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/source-profile.json b/prototypes/connections/results/2026-09-24-fixed-http/source-profile.json
new file mode 100644
index 0000000..50b7913
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/source-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35807,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "bce466328ac730ccb7cd22c7a0c4e2960bc94a0f20ac9f036e232bd499521ff7"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 43009,
+ "data": 1040,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "f39eaa24cad84a3ba34a5dd4b1c5bd6c23cdf18862ee3bb9bd6ba27cdba3f895"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-http/verified.json b/prototypes/connections/results/2026-09-24-fixed-http/verified.json
new file mode 100644
index 0000000..93a7ff3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-http/verified.json
@@ -0,0 +1,68 @@
+{
+ "profile": "build-time-prepared-http-document-host",
+ "fixed_source_cli_same_document": "pass",
+ "conditional_conflict_and_invalid_splice": "pass",
+ "one_mib_roundtrip_and_native_edit": "pass",
+ "slow_consumer_budget_and_release": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 7,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097177,
+ "server_structure_bytes": 40848
+ },
+ "source_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 6,
+ "commits": 1,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 6,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097162,
+ "server_structure_bytes": 41528
+ },
+ "limited_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048586,
+ "server_structure_bytes": 40848
+ },
+ "fixed_idle_rss_kib": 1520,
+ "source_idle_rss_kib": 1552,
+ "fixed_after_large_rss_kib": 1648,
+ "source_after_large_rss_kib": 1680,
+ "fixed_peak_rss_kib": 2128,
+ "source_peak_rss_kib": 1680,
+ "fixed_peak_rss_limit_kib": 4096,
+ "fixed_sha256": "02acf468f18610332d3fe4b9c093b2bbff08496000dbae2b61151d7f3a7a46fa",
+ "source_sha256": "f39eaa24cad84a3ba34a5dd4b1c5bd6c23cdf18862ee3bb9bd6ba27cdba3f895"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/memory-final.json b/prototypes/connections/results/2026-09-24-fixed-program/memory-final.json
new file mode 100644
index 0000000..a85054d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/memory-final.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "fixed-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, the embedded prepared program, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1104,
+ "one_mib_edit_rss_kib": 2128,
+ "one_mib_show_rss_kib": 1088
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "00f0316cb318cf168d4437080642fe1a6db013e7d4ad82be80e57ad9e12a0a3b",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/memory-verified.json b/prototypes/connections/results/2026-09-24-fixed-program/memory-verified.json
new file mode 100644
index 0000000..7ccf6ea
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/memory-verified.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "fixed-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, the embedded prepared program, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1104,
+ "one_mib_edit_rss_kib": 2112,
+ "one_mib_show_rss_kib": 1088
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/memory.json b/prototypes/connections/results/2026-09-24-fixed-program/memory.json
new file mode 100644
index 0000000..a4474ff
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/memory.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "fixed-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1088,
+ "one_mib_edit_rss_kib": 2128,
+ "one_mib_show_rss_kib": 1104
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "00f0316cb318cf168d4437080642fe1a6db013e7d4ad82be80e57ad9e12a0a3b",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/package-final.json b/prototypes/connections/results/2026-09-24-fixed-program/package-final.json
new file mode 100644
index 0000000..385f64a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/package-final.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "84aaf54f6471ddf5cb6fe735c2c3621baf567e186e7252f87e2930024d89ec58",
+ "archive_bytes": 14385,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/package.json b/prototypes/connections/results/2026-09-24-fixed-program/package.json
new file mode 100644
index 0000000..6671dd5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/package.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "5514e75fa29a9e2375e6ab5069a4b22f275d447725e63cb8b5c7245a9c966d7c",
+ "archive_bytes": 14386,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/parity-final-v2.json b/prototypes/connections/results/2026-09-24-fixed-program/parity-final-v2.json
new file mode 100644
index 0000000..73c6a66
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/parity-final-v2.json
@@ -0,0 +1,12 @@
+{
+ "profile": "build-time-prepared-native-document-runner",
+ "editor_create_edit_conflict_large_restore": "pass",
+ "dynamic_selection_and_invalid_range": "pass",
+ "nested_read_and_required_extent": "pass",
+ "invalid_compilation_preserves_previous_plan": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8",
+ "source_sha256": "bce466328ac730ccb7cd22c7a0c4e2960bc94a0f20ac9f036e232bd499521ff7",
+ "selection_sha256": "7d3394586fc9837a11a01bdae3aeeba2356b3abab8518e84545ede2ec1a6ab1c",
+ "excerpt_sha256": "b83a1fe42d45574ddf5941fdac2b759754d44da5705e6f33e5a45dabf7fd7205"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/parity-final.json b/prototypes/connections/results/2026-09-24-fixed-program/parity-final.json
new file mode 100644
index 0000000..6aa3d12
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/parity-final.json
@@ -0,0 +1,11 @@
+{
+ "profile": "build-time-prepared-native-document-runner",
+ "editor_create_edit_conflict_large_restore": "pass",
+ "dynamic_selection_and_invalid_range": "pass",
+ "nested_read_and_required_extent": "pass",
+ "invalid_compilation_preserves_previous_plan": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_sha256": "00f0316cb318cf168d4437080642fe1a6db013e7d4ad82be80e57ad9e12a0a3b",
+ "source_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03",
+ "selection_sha256": "836f883efb9dc86218c9606292b6c37241cc98277ce3ece03597795e076427a2"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/parity-reconfigured.json b/prototypes/connections/results/2026-09-24-fixed-program/parity-reconfigured.json
new file mode 100644
index 0000000..561a923
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/parity-reconfigured.json
@@ -0,0 +1,13 @@
+{
+ "profile": "build-time-prepared-native-document-runner",
+ "editor_create_edit_conflict_large_restore": "pass",
+ "dynamic_selection_and_invalid_range": "pass",
+ "nested_read_and_required_extent": "pass",
+ "invalid_compilation_preserves_previous_plan": "pass",
+ "same_directory_program_switch_rebuilds": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8",
+ "source_sha256": "bce466328ac730ccb7cd22c7a0c4e2960bc94a0f20ac9f036e232bd499521ff7",
+ "selection_sha256": "7d3394586fc9837a11a01bdae3aeeba2356b3abab8518e84545ede2ec1a6ab1c",
+ "excerpt_sha256": "b83a1fe42d45574ddf5941fdac2b759754d44da5705e6f33e5a45dabf7fd7205"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/parity-release.json b/prototypes/connections/results/2026-09-24-fixed-program/parity-release.json
new file mode 100644
index 0000000..994b69d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/parity-release.json
@@ -0,0 +1,14 @@
+{
+ "profile": "build-time-prepared-native-document-runner",
+ "editor_create_edit_conflict_large_restore": "pass",
+ "dynamic_selection_and_invalid_range": "pass",
+ "nested_read_and_required_extent": "pass",
+ "invalid_compilation_preserves_previous_plan": "pass",
+ "compiler_rejects_source_as_output": "pass",
+ "same_directory_program_switch_rebuilds": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8",
+ "source_sha256": "bce466328ac730ccb7cd22c7a0c4e2960bc94a0f20ac9f036e232bd499521ff7",
+ "selection_sha256": "7d3394586fc9837a11a01bdae3aeeba2356b3abab8518e84545ede2ec1a6ab1c",
+ "excerpt_sha256": "b83a1fe42d45574ddf5941fdac2b759754d44da5705e6f33e5a45dabf7fd7205"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/parity-verified.json b/prototypes/connections/results/2026-09-24-fixed-program/parity-verified.json
new file mode 100644
index 0000000..1350cfe
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/parity-verified.json
@@ -0,0 +1,12 @@
+{
+ "profile": "build-time-prepared-native-document-runner",
+ "editor_create_edit_conflict_large_restore": "pass",
+ "dynamic_selection_and_invalid_range": "pass",
+ "nested_read_and_required_extent": "pass",
+ "invalid_compilation_preserves_previous_plan": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_sha256": "00f0316cb318cf168d4437080642fe1a6db013e7d4ad82be80e57ad9e12a0a3b",
+ "source_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03",
+ "selection_sha256": "836f883efb9dc86218c9606292b6c37241cc98277ce3ece03597795e076427a2",
+ "excerpt_sha256": "221543dd8cee08b19c862d11d7a7f9c9c55d974964fb8fc88bf63792d96e14b9"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/parity.json b/prototypes/connections/results/2026-09-24-fixed-program/parity.json
new file mode 100644
index 0000000..76e1469
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/parity.json
@@ -0,0 +1,10 @@
+{
+ "profile": "build-time-prepared-native-document-runner",
+ "editor_create_edit_conflict_large_restore": "pass",
+ "dynamic_selection_and_invalid_range": "pass",
+ "invalid_compilation_preserves_previous_plan": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_sha256": "00f0316cb318cf168d4437080642fe1a6db013e7d4ad82be80e57ad9e12a0a3b",
+ "source_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03",
+ "selection_sha256": "836f883efb9dc86218c9606292b6c37241cc98277ce3ece03597795e076427a2"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/profile-final.json b/prototypes/connections/results/2026-09-24-fixed-program/profile-final.json
new file mode 100644
index 0000000..e6e530d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/profile-final.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked document runner with one build-time prepared app. The source parser and compiler are separate build tools. This 20 KiB text ceiling applies only to the recorded Linux AArch64/GCC 14 toolchain and excludes libc, heap, stack, and storage files.",
+ "budget_sha256": "e6f4e727172d1d75bf109f426e169c98fa635c9cc4757ffd3871035593aa00d8",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19244,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/profile.json b/prototypes/connections/results/2026-09-24-fixed-program/profile.json
new file mode 100644
index 0000000..771271e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked document runner with one build-time prepared app. The source parser and compiler are separate build tools. This 20 KiB text ceiling applies only to the recorded Linux AArch64/GCC 14 toolchain and excludes libc, heap, stack, and storage files.",
+ "budget_sha256": "e6f4e727172d1d75bf109f426e169c98fa635c9cc4757ffd3871035593aa00d8",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19244,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "00f0316cb318cf168d4437080642fe1a6db013e7d4ad82be80e57ad9e12a0a3b"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/pure-document-fixed-final-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-fixed-program/pure-document-fixed-final-linux-aarch64.tar.gz
new file mode 100644
index 0000000..511d53f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/pure-document-fixed-final-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/pure-document-fixed-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-fixed-program/pure-document-fixed-linux-aarch64.tar.gz
new file mode 100644
index 0000000..ea09bcb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/pure-document-fixed-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-fixed-program/window-regression.json b/prototypes/connections/results/2026-09-24-fixed-program/window-regression.json
new file mode 100644
index 0000000..44483d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-program/window-regression.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_line_width": 80, "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [47328, 48048], "large_window_rss_kib": 44112, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui-final/package.json b/prototypes/connections/results/2026-09-24-fixed-tui-final/package.json
new file mode 100644
index 0000000..86651ee
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui-final/package.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "3c5aa21f36a410bcef5b42c4928b2b24e35a55f7b6d5e62d322b749b48512db6",
+ "archive_bytes": 33654,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui-final/profile.json b/prototypes/connections/results/2026-09-24-fixed-tui-final/profile.json
new file mode 100644
index 0000000..52ebb29
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui-final/profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS is checked by check_tui.py on the recorded Linux AArch64 host.",
+ "budget_sha256": "e378cb302b2a4bcd2ee674af048116f139b214b59f24244d6c825bc71a8e8a31",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "sections": {
+ "text": 28226,
+ "data": 988,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "dd6fb1f48a0212b59c4b997bd72ce099ad53f0b2d0d63cdebbc5264fc9bf23f5"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui-final/pty-flow.json b/prototypes/connections/results/2026-09-24-fixed-tui-final/pty-flow.json
new file mode 100644
index 0000000..8e134d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui-final/pty-flow.json
@@ -0,0 +1,16 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "UTF-8 codepoint movement and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "one MiB document edit and fresh CLI restore",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1744,
+ "one_mib_peak_rss_kib": 3168,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "dd6fb1f48a0212b59c4b997bd72ce099ad53f0b2d0d63cdebbc5264fc9bf23f5"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui-final/pty-sanitized.json b/prototypes/connections/results/2026-09-24-fixed-tui-final/pty-sanitized.json
new file mode 100644
index 0000000..a5ca7da
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui-final/pty-sanitized.json
@@ -0,0 +1,16 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "UTF-8 codepoint movement and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "one MiB document edit and fresh CLI restore",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 9840,
+ "one_mib_peak_rss_kib": 11712,
+ "one_mib_peak_rss_limit_kib": 0,
+ "binary_sha256": "746ebdfa531accd578ed04132a6d4155a0c8cf44842f30c46cc49ef804f19615"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui-final/pure-document-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-fixed-tui-final/pure-document-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..596d28b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui-final/pure-document-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui/package-cursor.json b/prototypes/connections/results/2026-09-24-fixed-tui/package-cursor.json
new file mode 100644
index 0000000..ae2716d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui/package-cursor.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "0e7d03741e17cc2f39db95aa28e52b8fdd02a54b68c8e978df06407cc241c2bb",
+ "archive_bytes": 33625,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui/package.json b/prototypes/connections/results/2026-09-24-fixed-tui/package.json
new file mode 100644
index 0000000..ae2716d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui/package.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "0e7d03741e17cc2f39db95aa28e52b8fdd02a54b68c8e978df06407cc241c2bb",
+ "archive_bytes": 33625,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui/profile.json b/prototypes/connections/results/2026-09-24-fixed-tui/profile.json
new file mode 100644
index 0000000..acc451b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui/profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS is checked by check_tui.py on the recorded Linux AArch64 host.",
+ "budget_sha256": "e378cb302b2a4bcd2ee674af048116f139b214b59f24244d6c825bc71a8e8a31",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "sections": {
+ "text": 28098,
+ "data": 988,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "ae3f8ff479899929cb108dd3435750aa24b8f793744a9e7794315974182ad1f7"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui/pty-cursor-flow.json b/prototypes/connections/results/2026-09-24-fixed-tui/pty-cursor-flow.json
new file mode 100644
index 0000000..c85112d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui/pty-cursor-flow.json
@@ -0,0 +1,16 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "UTF-8 codepoint movement and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "one MiB document edit and fresh CLI restore",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1744,
+ "one_mib_peak_rss_kib": 3168,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "ae3f8ff479899929cb108dd3435750aa24b8f793744a9e7794315974182ad1f7"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui/pty-cursor-sanitized.json b/prototypes/connections/results/2026-09-24-fixed-tui/pty-cursor-sanitized.json
new file mode 100644
index 0000000..7852c5d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui/pty-cursor-sanitized.json
@@ -0,0 +1,16 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "UTF-8 codepoint movement and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "one MiB document edit and fresh CLI restore",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 9808,
+ "one_mib_peak_rss_kib": 11760,
+ "one_mib_peak_rss_limit_kib": 0,
+ "binary_sha256": "71eeef473231fe7b693022fad39fe3b9b90e89913bbc252a2b64e6d087b1ebf6"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui/pty-flow.json b/prototypes/connections/results/2026-09-24-fixed-tui/pty-flow.json
new file mode 100644
index 0000000..50f5cfa
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui/pty-flow.json
@@ -0,0 +1,16 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "create and save through terminal",
+ "open another key",
+ "UTF-8 edit and save",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "one MiB document edit and fresh CLI restore",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1744,
+ "one_mib_peak_rss_kib": 2784,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "ae3f8ff479899929cb108dd3435750aa24b8f793744a9e7794315974182ad1f7"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui/pty-sanitized.json b/prototypes/connections/results/2026-09-24-fixed-tui/pty-sanitized.json
new file mode 100644
index 0000000..443e9cd
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui/pty-sanitized.json
@@ -0,0 +1,16 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "create and save through terminal",
+ "open another key",
+ "UTF-8 edit and save",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "one MiB document edit and fresh CLI restore",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 9776,
+ "one_mib_peak_rss_kib": 11712,
+ "one_mib_peak_rss_limit_kib": 0,
+ "binary_sha256": "71eeef473231fe7b693022fad39fe3b9b90e89913bbc252a2b64e6d087b1ebf6"
+}
diff --git a/prototypes/connections/results/2026-09-24-fixed-tui/pure-document-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-fixed-tui/pure-document-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..05a8713
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-fixed-tui/pure-document-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-flat-export-source/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-flat-export-source/pure-source-preview.tar.gz
new file mode 100644
index 0000000..096ffe4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-flat-export-source/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-flat-export-source/source-check-linux-aarch64.json b/prototypes/connections/results/2026-09-24-flat-export-source/source-check-linux-aarch64.json
new file mode 100644
index 0000000..854f2d0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-flat-export-source/source-check-linux-aarch64.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "16126434bdbef5b75210639cf67f5e27711aa7c540ba1ca6d3949dd45009df9d",
+ "archive_bytes": 329118,
+ "source_files": 168,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean selected page store exports mixed revisions to the default flat store",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-flat-export/export-check.json b/prototypes/connections/results/2026-09-24-flat-export/export-check.json
new file mode 100644
index 0000000..c64ad9e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-flat-export/export-check.json
@@ -0,0 +1,27 @@
+{
+ "objects": 5,
+ "logical_bytes": 1081346,
+ "document_digest": "efaa71ebcdaf493723b82bc98532aba3fd5beace476f8b9f61f93706bddf850b",
+ "paged_reader_sha256": "f29440fcc167d1202b226f0faee450cb299989c8977277e062a330587cec5e39",
+ "flat_reader_sha256": "04974e2d3c4d7f5fb22aff67e7399aa2ebcbd85eb24da0c0e41f3ef047d5ddec",
+ "passed": true,
+ "extra_documents": 0,
+ "source_revisions": {
+ "empty": 1,
+ "small": 1,
+ "boundary": 1,
+ "large": 1,
+ "megabyte": 66
+ },
+ "readback_sha256": {
+ "empty": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "small": "4b68ab3847feda7d6c62c1fbcbeebfa35eab7351ed5e78f4ddadea5df64b8015",
+ "boundary": "1bd4db450abc8914c2fac721cace2704ff4c16028e6d07293154dad289835694",
+ "large": "b10b6985790c800b653eeb8e979f9c1551293ee9c293cbca1c4741df09cc8284",
+ "megabyte": "3cacf45be36c19ea18974a474bd2c668f24622b9132ab99294b3778ba0124094"
+ },
+ "flat_edit_after_export": "revision 67",
+ "writer_busy_during_export_and_resumed_after": true,
+ "partial_export_not_published": true,
+ "existing_target_and_symlink_rejected": true
+}
diff --git a/prototypes/connections/results/2026-09-24-flat-export/export-ext4.json b/prototypes/connections/results/2026-09-24-flat-export/export-ext4.json
new file mode 100644
index 0000000..3fc4829
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-flat-export/export-ext4.json
@@ -0,0 +1,28 @@
+{
+ "objects": 5,
+ "logical_bytes": 1081346,
+ "document_digest": "efaa71ebcdaf493723b82bc98532aba3fd5beace476f8b9f61f93706bddf850b",
+ "paged_reader_sha256": "f29440fcc167d1202b226f0faee450cb299989c8977277e062a330587cec5e39",
+ "flat_reader_sha256": "04974e2d3c4d7f5fb22aff67e7399aa2ebcbd85eb24da0c0e41f3ef047d5ddec",
+ "passed": true,
+ "extra_documents": 0,
+ "scratch_parent": "/home/eunhhu/work/pure/prototypes/connections/build",
+ "source_revisions": {
+ "empty": 1,
+ "small": 1,
+ "boundary": 1,
+ "large": 1,
+ "megabyte": 66
+ },
+ "readback_sha256": {
+ "empty": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "small": "4b68ab3847feda7d6c62c1fbcbeebfa35eab7351ed5e78f4ddadea5df64b8015",
+ "boundary": "1bd4db450abc8914c2fac721cace2704ff4c16028e6d07293154dad289835694",
+ "large": "b10b6985790c800b653eeb8e979f9c1551293ee9c293cbca1c4741df09cc8284",
+ "megabyte": "3cacf45be36c19ea18974a474bd2c668f24622b9132ab99294b3778ba0124094"
+ },
+ "flat_edit_after_export": "revision 67",
+ "writer_busy_during_export_and_resumed_after": true,
+ "partial_export_not_published": true,
+ "existing_target_and_symlink_rejected": true
+}
diff --git a/prototypes/connections/results/2026-09-24-flat-export/export-scale-1024.json b/prototypes/connections/results/2026-09-24-flat-export/export-scale-1024.json
new file mode 100644
index 0000000..20a2d33
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-flat-export/export-scale-1024.json
@@ -0,0 +1,27 @@
+{
+ "objects": 1029,
+ "logical_bytes": 1212418,
+ "document_digest": "59dabf364a2b8d06e74c275d3679a15b71095544981e90ccbb0932b096c380d1",
+ "paged_reader_sha256": "f29440fcc167d1202b226f0faee450cb299989c8977277e062a330587cec5e39",
+ "flat_reader_sha256": "04974e2d3c4d7f5fb22aff67e7399aa2ebcbd85eb24da0c0e41f3ef047d5ddec",
+ "passed": true,
+ "extra_documents": 1024,
+ "source_revisions": {
+ "empty": 1,
+ "small": 1,
+ "boundary": 1,
+ "large": 1,
+ "megabyte": 66
+ },
+ "readback_sha256": {
+ "empty": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "small": "4b68ab3847feda7d6c62c1fbcbeebfa35eab7351ed5e78f4ddadea5df64b8015",
+ "boundary": "1bd4db450abc8914c2fac721cace2704ff4c16028e6d07293154dad289835694",
+ "large": "b10b6985790c800b653eeb8e979f9c1551293ee9c293cbca1c4741df09cc8284",
+ "megabyte": "3cacf45be36c19ea18974a474bd2c668f24622b9132ab99294b3778ba0124094"
+ },
+ "flat_edit_after_export": "revision 67",
+ "writer_busy_during_export_and_resumed_after": true,
+ "partial_export_not_published": true,
+ "existing_target_and_symlink_rejected": true
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/app-asan.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/app-asan.json
new file mode 100644
index 0000000..9bd2b7c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/app-asan.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 11,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115421,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 60,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 14,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 45,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 15,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "bf418bdfd09f865d327c42bd598c3f251138f19e7e6ae0031c4b497affc55002",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "4ae184e15f9f4120333882bd90ea15668bbdaf1cf4fa39f3eb76ba311d129061",
+ "editor_sha256": "4f2875d8cc8ccd170d4d959f2491c124b1ac11b1debb38ba7f318be1982c8fb6",
+ "binary_sha256": "ae727ef73c5118acb3a96337ffee7f990f061c597aa22d3d818b1865da06ca6c",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store-paged.c": "da01d9e0e4607ac78d9b057431e1ae6d9bd9aeb9036178b388a1bf1fbe2e7b17",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "58526592ee906833718101f1d33878d66c5e357097d5347d02755d922c36dda9",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "584f6671c2daf40ee3cc4233760b0004d5035bd0e0cd10aa0fe6a0b814f66937",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/app-release.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/app-release.json
new file mode 100644
index 0000000..ca41eb7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/app-release.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11753,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 34,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 15,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "b9642410766ffc6dad9ed3ac38ce9ef550e3a861deb21a4e53dea219687894b6",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "a7e9ec3814b9adf81254bb781a98ac5c2896f69f665e80307f5ec1d824d1089f",
+ "editor_sha256": "e024d1829ea1a2211c58c33b8ae457794cbda0dbf927cdcb1126cd4de13a16e9",
+ "binary_sha256": "09b8fb1695ea4ff3a326e75660e77a4e5532f908de7e6fb01a9dec6c840a0d53",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store-paged.c": "da01d9e0e4607ac78d9b057431e1ae6d9bd9aeb9036178b388a1bf1fbe2e7b17",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "58526592ee906833718101f1d33878d66c5e357097d5347d02755d922c36dda9",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "584f6671c2daf40ee3cc4233760b0004d5035bd0e0cd10aa0fe6a0b814f66937",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/gtk-flow.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/gtk-flow.json
new file mode 100644
index 0000000..233cfc4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/gtk-flow.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 43632, "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/memory.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/memory.json
new file mode 100644
index 0000000..e2068b8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/memory.json
@@ -0,0 +1,14 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1056,
+ "one_mib_edit_rss_kib": 2080,
+ "one_mib_show_rss_kib": 1056
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "e024d1829ea1a2211c58c33b8ae457794cbda0dbf927cdcb1126cd4de13a16e9",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/package-full.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/package-full.json
new file mode 100644
index 0000000..a753696
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/package-full.json
@@ -0,0 +1,21 @@
+{
+ "archive_sha256": "40e635bdd6746e13c1073a1d809d8753ddfab94cf973be2771ea9f8ffff0fb3c",
+ "archive_bytes": 114025,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-connections",
+ "pure-document-peer",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "selected storage keeps small values inline and maps large values",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted HTTP host updates the same document as the native CLI",
+ "extracted C/Python TLS peers share a 1 MiB document and recover",
+ "extracted GTK window and selected external host edit the same document"
+ ],
+ "peer_idle_rss_kib": 7840,
+ "peer_after_large_work_rss_kib": 9504
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/package-micro.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/package-micro.json
new file mode 100644
index 0000000..dccd086
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/package-micro.json
@@ -0,0 +1,13 @@
+{
+ "archive_sha256": "0d3a5da21ebd94cd235259ccfee9173c44afee57e57514e05acc1a43beea8a36",
+ "archive_bytes": 26045,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "selected storage keeps small values inline and maps large values",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/peer.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/peer.json
new file mode 100644
index 0000000..99de24a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/peer.json
@@ -0,0 +1,16 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 7856,
+ "server_after_large_work_rss_kib": 9520
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/profile.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/profile.json
new file mode 100644
index 0000000..c0ae382
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-hybrid-document-storage",
+ "scope": "Opt-in inline/PUREP001 document store on Linux AArch64/GCC 14. The CLI text ceiling is 42 KiB: 2 KiB above the original selected-page gate because the measured 41064-byte dual-format build fails 40 KiB. This is an explicit research budget, not the default micro-runtime budget. Direct dependencies only; excludes libc, process RAM, filesystem cache and journal, optional TLS/GTK.",
+ "budget_sha256": "038a323d8492731611dfc56e799e7da751946fe0ea5dc428550ff02ffd781b29",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 41064,
+ "data": 1000,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "e024d1829ea1a2211c58c33b8ae457794cbda0dbf927cdcb1126cd4de13a16e9"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 47928,
+ "data": 1088,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "09b8fb1695ea4ff3a326e75660e77a4e5532f908de7e6fb01a9dec6c840a0d53"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/pure-document-hybrid-authoring-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/pure-document-hybrid-authoring-linux-aarch64.tar.gz
new file mode 100644
index 0000000..20dec18
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/pure-document-hybrid-authoring-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/pure-document-hybrid-micro-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/pure-document-hybrid-micro-linux-aarch64.tar.gz
new file mode 100644
index 0000000..0234d2b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/pure-document-hybrid-micro-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/small-scan.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/small-scan.json
new file mode 100644
index 0000000..4dda494
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/small-scan.json
@@ -0,0 +1,5 @@
+{
+ "small_edit_store_directory_scans": 0,
+ "unrelated_directory_entries": 256,
+ "binary_sha256": "e024d1829ea1a2211c58c33b8ae457794cbda0dbf927cdcb1126cd4de13a16e9"
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/unit-asan.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/unit-asan.json
new file mode 100644
index 0000000..8da4fd1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/unit-asan.json
@@ -0,0 +1 @@
+{"hybrid_storage":"snapshot-patch-range-compaction-crash-conflict-uncertain-inline-transitions","mixed_edits":128}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/unit.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/unit.json
new file mode 100644
index 0000000..8da4fd1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/unit.json
@@ -0,0 +1 @@
+{"hybrid_storage":"snapshot-patch-range-compaction-crash-conflict-uncertain-inline-transitions","mixed_edits":128}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage-v2/write-cost.json b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/write-cost.json
new file mode 100644
index 0000000..266c4c8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage-v2/write-cost.json
@@ -0,0 +1,49 @@
+{
+ "profile": "linux-aarch64-16k-page-document-replacement",
+ "candidate_mode": "hybrid",
+ "workloads": [
+ "replace last byte of 1 MiB document",
+ "replace one-byte document"
+ ],
+ "unit": "successful user-space write syscall bytes targeting object files",
+ "excludes": "physical device writes, filesystem journal, metadata and directory sync cost",
+ "one_mib": {
+ "flat": {
+ "object_write_syscall_bytes": 1048600,
+ "object_write_calls": 258,
+ "object_files": {
+ "obj-large": 1048600
+ },
+ "binary_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03"
+ },
+ "hybrid": {
+ "object_write_syscall_bytes": 16944,
+ "object_write_calls": 3,
+ "object_files": {
+ "obj-large": 560,
+ "dat-large-0000000000000001": 1064960
+ },
+ "binary_sha256": "e024d1829ea1a2211c58c33b8ae457794cbda0dbf927cdcb1126cd4de13a16e9"
+ },
+ "flat_to_hybrid_ratio": 61.8862134088763
+ },
+ "one_byte": {
+ "flat": {
+ "object_write_syscall_bytes": 25,
+ "object_write_calls": 2,
+ "object_files": {
+ "obj-tiny": 25
+ },
+ "binary_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03"
+ },
+ "hybrid": {
+ "object_write_syscall_bytes": 25,
+ "object_write_calls": 2,
+ "object_files": {
+ "obj-tiny": 25
+ },
+ "binary_sha256": "e024d1829ea1a2211c58c33b8ae457794cbda0dbf927cdcb1126cd4de13a16e9"
+ },
+ "hybrid_to_flat_ratio": 1.0
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/app-asan.json b/prototypes/connections/results/2026-09-24-hybrid-storage/app-asan.json
new file mode 100644
index 0000000..77ff376
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/app-asan.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "03ae899315468bf32215398b094b120c528c36e6337e6da5ebb3435204c2ab82",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "f4761e52b1b65af4b7fd89f3eaa456ca69aa5c0e61e3ade24b0b04c9377af974",
+ "editor_sha256": "d94ddba81b79796aab53b4131d05332e02e654c35007f48d9073ce410c5ecee0",
+ "binary_sha256": "db7fd98350bf3a33435921035871f33e18dad0a3b28360671544a3d34a6a93ce",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store-paged.c": "02c5992465d117e576199c7348daa2b628e6c6efd41d906faa3b50713ece9f53",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "58526592ee906833718101f1d33878d66c5e357097d5347d02755d922c36dda9",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "584f6671c2daf40ee3cc4233760b0004d5035bd0e0cd10aa0fe6a0b814f66937",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/app-release.json b/prototypes/connections/results/2026-09-24-hybrid-storage/app-release.json
new file mode 100644
index 0000000..452cadb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/app-release.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 14227,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 16,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "dd505a9c4ecf73205f33edb491ed990234cd940c6164cd9fe56c1606dc4a280f",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "9b7366c1d005a21c393425e28c18bd161fcbb86af3961180780d67f5d62ba3d8",
+ "editor_sha256": "5ea320034f2c36f378bed30bb12705f35723dd9f7f334c976aec7d6f5927ac57",
+ "binary_sha256": "8bc87de02efca32d1281976a8e8bea2e5a7242eb5ec07fc204b7762c2081021c",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store-paged.c": "02c5992465d117e576199c7348daa2b628e6c6efd41d906faa3b50713ece9f53",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "58526592ee906833718101f1d33878d66c5e357097d5347d02755d922c36dda9",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "584f6671c2daf40ee3cc4233760b0004d5035bd0e0cd10aa0fe6a0b814f66937",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/gtk-flow.json b/prototypes/connections/results/2026-09-24-hybrid-storage/gtk-flow.json
new file mode 100644
index 0000000..4bff12d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/gtk-flow.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 43760, "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/memory.json b/prototypes/connections/results/2026-09-24-hybrid-storage/memory.json
new file mode 100644
index 0000000..64304e0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/memory.json
@@ -0,0 +1,14 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1056,
+ "one_mib_edit_rss_kib": 2080,
+ "one_mib_show_rss_kib": 1056
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "5ea320034f2c36f378bed30bb12705f35723dd9f7f334c976aec7d6f5927ac57",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/package-full.json b/prototypes/connections/results/2026-09-24-hybrid-storage/package-full.json
new file mode 100644
index 0000000..0675a20
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/package-full.json
@@ -0,0 +1,21 @@
+{
+ "archive_sha256": "0aa6141240a44039ec5c3e542c9c2857678620c77c81203dd984b4121b18adce",
+ "archive_bytes": 114009,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-connections",
+ "pure-document-peer",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "selected storage keeps small values inline and maps large values",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted HTTP host updates the same document as the native CLI",
+ "extracted C/Python TLS peers share a 1 MiB document and recover",
+ "extracted GTK window and selected external host edit the same document"
+ ],
+ "peer_idle_rss_kib": 7840,
+ "peer_after_large_work_rss_kib": 9536
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/package-micro.json b/prototypes/connections/results/2026-09-24-hybrid-storage/package-micro.json
new file mode 100644
index 0000000..62cfd78
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/package-micro.json
@@ -0,0 +1,13 @@
+{
+ "archive_sha256": "c67a92e534a43aed24254995078bb72992015766da9c3e57ec7c993fa50f3654",
+ "archive_bytes": 26040,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "selected storage keeps small values inline and maps large values",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/peer.json b/prototypes/connections/results/2026-09-24-hybrid-storage/peer.json
new file mode 100644
index 0000000..fa238e3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/peer.json
@@ -0,0 +1,16 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 7840,
+ "server_after_large_work_rss_kib": 9536
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/profile.json b/prototypes/connections/results/2026-09-24-hybrid-storage/profile.json
new file mode 100644
index 0000000..96ca222
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-hybrid-document-storage",
+ "scope": "Opt-in inline/PUREP001 document store on Linux AArch64/GCC 14. The CLI text ceiling is 42 KiB: 2 KiB above the original selected-page gate because the measured 41064-byte dual-format build fails 40 KiB. This is an explicit research budget, not the default micro-runtime budget. Direct dependencies only; excludes libc, process RAM, filesystem cache and journal, optional TLS/GTK.",
+ "budget_sha256": "038a323d8492731611dfc56e799e7da751946fe0ea5dc428550ff02ffd781b29",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 41064,
+ "data": 1000,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "5ea320034f2c36f378bed30bb12705f35723dd9f7f334c976aec7d6f5927ac57"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 47928,
+ "data": 1088,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "8bc87de02efca32d1281976a8e8bea2e5a7242eb5ec07fc204b7762c2081021c"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/pure-document-hybrid-authoring-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-hybrid-storage/pure-document-hybrid-authoring-linux-aarch64.tar.gz
new file mode 100644
index 0000000..5280fd4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/pure-document-hybrid-authoring-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/pure-document-hybrid-micro-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-hybrid-storage/pure-document-hybrid-micro-linux-aarch64.tar.gz
new file mode 100644
index 0000000..c2fb13f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/pure-document-hybrid-micro-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/unit-asan.json b/prototypes/connections/results/2026-09-24-hybrid-storage/unit-asan.json
new file mode 100644
index 0000000..8da4fd1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/unit-asan.json
@@ -0,0 +1 @@
+{"hybrid_storage":"snapshot-patch-range-compaction-crash-conflict-uncertain-inline-transitions","mixed_edits":128}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/unit.json b/prototypes/connections/results/2026-09-24-hybrid-storage/unit.json
new file mode 100644
index 0000000..8da4fd1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/unit.json
@@ -0,0 +1 @@
+{"hybrid_storage":"snapshot-patch-range-compaction-crash-conflict-uncertain-inline-transitions","mixed_edits":128}
diff --git a/prototypes/connections/results/2026-09-24-hybrid-storage/write-cost.json b/prototypes/connections/results/2026-09-24-hybrid-storage/write-cost.json
new file mode 100644
index 0000000..a3dfa76
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-hybrid-storage/write-cost.json
@@ -0,0 +1,49 @@
+{
+ "profile": "linux-aarch64-16k-page-document-replacement",
+ "candidate_mode": "hybrid",
+ "workloads": [
+ "replace last byte of 1 MiB document",
+ "replace one-byte document"
+ ],
+ "unit": "successful user-space write syscall bytes targeting object files",
+ "excludes": "physical device writes, filesystem journal, metadata and directory sync cost",
+ "one_mib": {
+ "flat": {
+ "object_write_syscall_bytes": 1048600,
+ "object_write_calls": 258,
+ "object_files": {
+ "obj-large": 1048600
+ },
+ "binary_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03"
+ },
+ "hybrid": {
+ "object_write_syscall_bytes": 16944,
+ "object_write_calls": 3,
+ "object_files": {
+ "obj-large": 560,
+ "dat-large-0000000000000001": 1064960
+ },
+ "binary_sha256": "5ea320034f2c36f378bed30bb12705f35723dd9f7f334c976aec7d6f5927ac57"
+ },
+ "flat_to_hybrid_ratio": 61.8862134088763
+ },
+ "one_byte": {
+ "flat": {
+ "object_write_syscall_bytes": 25,
+ "object_write_calls": 2,
+ "object_files": {
+ "obj-tiny": 25
+ },
+ "binary_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03"
+ },
+ "hybrid": {
+ "object_write_syscall_bytes": 25,
+ "object_write_calls": 2,
+ "object_files": {
+ "obj-tiny": 25
+ },
+ "binary_sha256": "5ea320034f2c36f378bed30bb12705f35723dd9f7f334c976aec7d6f5927ac57"
+ },
+ "hybrid_to_flat_ratio": 1.0
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-wake/archived-comparison.json b/prototypes/connections/results/2026-09-24-idle-wake/archived-comparison.json
new file mode 100644
index 0000000..f90f1a9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-wake/archived-comparison.json
@@ -0,0 +1,21 @@
+{
+ "profile": "idle-http-host-poll-syscalls",
+ "observation_seconds": 1.25,
+ "before": {
+ "poll_calls": 25,
+ "timeout_values_ms": [
+ 50
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=PO",
+ "binary_sha256": "7dd0010fa6d6024afa2fe35d57a4c73f33ac632e732616ac8f8853d7b22d79b3"
+ },
+ "after": {
+ "poll_calls": 1,
+ "timeout_values_ms": [
+ -1
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, NULL, NULL, 0) = ? ERESTARTNOHAND (To be restarted if no handler)\n--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=927636, si_uid=1000} ---\n",
+ "binary_sha256": "3e8162f6851ba407061d1109a87b9b2b17c87a5c5eadbc75ea7cc0fb27a84501"
+ },
+ "deadline_driven_idle_wait": "pass"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-wake/fixed-profile.json b/prototypes/connections/results/2026-09-24-idle-wake/fixed-profile.json
new file mode 100644
index 0000000..9a57d8c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-wake/fixed-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files.",
+ "budget_sha256": "2b7e550992abb1872e52846dec712fab59b78692b776fd7e648d7976299f4b2a",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19244,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8"
+ },
+ "pure-connections-fixed": {
+ "sections": {
+ "text": 25292,
+ "data": 1000,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "3e8162f6851ba407061d1109a87b9b2b17c87a5c5eadbc75ea7cc0fb27a84501"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-wake/fixed-server-regression.json b/prototypes/connections/results/2026-09-24-idle-wake/fixed-server-regression.json
new file mode 100644
index 0000000..5400394
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-wake/fixed-server-regression.json
@@ -0,0 +1,68 @@
+{
+ "profile": "build-time-prepared-http-document-host",
+ "fixed_source_cli_same_document": "pass",
+ "conditional_conflict_and_invalid_splice": "pass",
+ "one_mib_roundtrip_and_native_edit": "pass",
+ "slow_consumer_budget_and_release": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 7,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097177,
+ "server_structure_bytes": 40848
+ },
+ "source_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 6,
+ "commits": 1,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 6,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097162,
+ "server_structure_bytes": 41528
+ },
+ "limited_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048586,
+ "server_structure_bytes": 40848
+ },
+ "fixed_idle_rss_kib": 1504,
+ "source_idle_rss_kib": 1536,
+ "fixed_after_large_rss_kib": 1632,
+ "source_after_large_rss_kib": 1664,
+ "fixed_peak_rss_kib": 2128,
+ "source_peak_rss_kib": 1664,
+ "fixed_peak_rss_limit_kib": 4096,
+ "fixed_sha256": "3e8162f6851ba407061d1109a87b9b2b17c87a5c5eadbc75ea7cc0fb27a84501",
+ "source_sha256": "186fd0ab0f7cd32cc46a341cc4e6ec784126193810473c6ac28a8c95a0d44bc3"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-wake/idle.json b/prototypes/connections/results/2026-09-24-idle-wake/idle.json
new file mode 100644
index 0000000..dee7a74
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-wake/idle.json
@@ -0,0 +1,21 @@
+{
+ "profile": "idle-http-host-poll-syscalls",
+ "observation_seconds": 1.25,
+ "before": {
+ "poll_calls": 25,
+ "timeout_values_ms": [
+ 50
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=PO",
+ "binary_sha256": "02acf468f18610332d3fe4b9c093b2bbff08496000dbae2b61151d7f3a7a46fa"
+ },
+ "after": {
+ "poll_calls": 1,
+ "timeout_values_ms": [
+ -1
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, NULL, NULL, 0) = ? ERESTARTNOHAND (To be restarted if no handler)\n--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=927237, si_uid=1000} ---\n",
+ "binary_sha256": "3e8162f6851ba407061d1109a87b9b2b17c87a5c5eadbc75ea7cc0fb27a84501"
+ },
+ "deadline_driven_idle_wait": "pass"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-wake/package.json b/prototypes/connections/results/2026-09-24-idle-wake/package.json
new file mode 100644
index 0000000..61d484b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-wake/package.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "669d28751faa4da34dd63cb52e83fa2cfb11146a9844b0f6378f9f63500a0b71",
+ "archive_bytes": 31773,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-wake/pure-document-fixed-http-idle-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-idle-wake/pure-document-fixed-http-idle-linux-aarch64.tar.gz
new file mode 100644
index 0000000..24d9b3d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-wake/pure-document-fixed-http-idle-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-idle-wake/reproducible-comparison.json b/prototypes/connections/results/2026-09-24-idle-wake/reproducible-comparison.json
new file mode 100644
index 0000000..4a17350
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-wake/reproducible-comparison.json
@@ -0,0 +1,21 @@
+{
+ "profile": "idle-http-host-poll-syscalls",
+ "observation_seconds": 1.25,
+ "before": {
+ "poll_calls": 25,
+ "timeout_values_ms": [
+ 50
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=PO",
+ "binary_sha256": "7dd0010fa6d6024afa2fe35d57a4c73f33ac632e732616ac8f8853d7b22d79b3"
+ },
+ "after": {
+ "poll_calls": 1,
+ "timeout_values_ms": [
+ -1
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, NULL, NULL, 0) = ? ERESTARTNOHAND (To be restarted if no handler)\n--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=928742, si_uid=1000} ---\n",
+ "binary_sha256": "3e8162f6851ba407061d1109a87b9b2b17c87a5c5eadbc75ea7cc0fb27a84501"
+ },
+ "deadline_driven_idle_wait": "pass"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-wake/source-profile.json b/prototypes/connections/results/2026-09-24-idle-wake/source-profile.json
new file mode 100644
index 0000000..05a247c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-wake/source-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35807,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "bce466328ac730ccb7cd22c7a0c4e2960bc94a0f20ac9f036e232bd499521ff7"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 43073,
+ "data": 1040,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "186fd0ab0f7cd32cc46a341cc4e6ec784126193810473c6ac28a8c95a0d44bc3"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/async-core.json b/prototypes/connections/results/2026-09-24-idle-work-binding/async-core.json
new file mode 100644
index 0000000..4843a89
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/async-core.json
@@ -0,0 +1,55 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "selected-owner-thread-async-effects",
+ "max_text_bytes": 8192,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "effect_bytes": 128
+ },
+ "archive_members": [
+ "runtime-async.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Selected owner-thread completion extension. Host I/O and worker stacks are excluded. The default execution core and fixed document packages do not link this profile."
+ },
+ "layout": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8,
+ "effect_bytes": 128
+ },
+ "sections": {
+ "text": 7456,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime-async.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 6536\t 0\t 0\t 6536\t 1988\truntime-async.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution-async.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution-async.a)\n",
+ "archive_sha256": "897fb2f6eff5dd07efcf0789107bfcf87423fc90aae084df169601451f23d07f",
+ "layout_binary_sha256": "71866a57a3a2af37a8e3d4f2f97669c482b11b3a408a1d918e5de068dab9e34a",
+ "budget_sha256": "496e34596e24418efb46e460126b7d67492137207be988525abda1397d70c539",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/async-gated.json b/prototypes/connections/results/2026-09-24-idle-work-binding/async-gated.json
new file mode 100644
index 0000000..92f9838
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/async-gated.json
@@ -0,0 +1,53 @@
+{
+ "async_http": "snapshot-read-write-overlap-deadline-recovery-draining-shutdown",
+ "before_publication": {
+ "status": 200,
+ "etag": "\"1\"",
+ "body": "old"
+ },
+ "after_publication": {
+ "status": 200,
+ "etag": "\"2\"",
+ "body": "oldafter"
+ },
+ "shutdown_restore": {
+ "revision": "2",
+ "body": "oldafter"
+ },
+ "deadline_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 1,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 43320
+ },
+ "shutdown_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 13,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 13,
+ "borrowed_output_bytes": 5,
+ "server_structure_bytes": 43320
+ },
+ "test_source_sha256": "f38c9d3d784676ce815c276fbffc10e00f767aaa803793d8db311c19ef3b9085",
+ "gated_test_binary_sha256": "cb4e7209c53261b63647823aaa8ee408a860d1ccde6c85bc404d77a336128eb2"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/async-server-profile.json b/prototypes/connections/results/2026-09-24-idle-work-binding/async-server-profile.json
new file mode 100644
index 0000000..a3a89b8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/async-server-profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-read-write-document-http",
+ "scope": "Optional one-read/one-write-worker HTTP host on the recorded Linux AArch64/GCC 14 toolchain. Section limits exclude the two 128 KiB worker stacks, libc, heap, mapped files and kernel buffers. Default CLI and HTTP do not link this option. Inspect process RSS and VM separately.",
+ "budget_sha256": "acd82386572fc2f874ca2fee5f4eed68ee145cf990d7315a9f1aff06daf51995",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-connections-async": {
+ "sections": {
+ "text": 48561,
+ "data": 1180,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "9485151b8902d66052bb689e821b502810b66561e0a251d3ce091c4919b7c67e"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/cli-check.json b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-check.json
new file mode 100644
index 0000000..1f60a56
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "927e9b0f7bc672e661da0d82abe60aaf3743f6753fbb00e6b39035a3239bae22",
+ "archive_bytes": 12987,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-check.json b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-check.json
new file mode 100644
index 0000000..0f372bf
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "177bb19c9790712ccb8f75fd65eb59b02c68b526b5155d3b1e83a795c845f031",
+ "archive_bytes": 28719,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-tui-check.json b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-tui-check.json
new file mode 100644
index 0000000..5a6506c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-tui-check.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "081e5fe6205760e343ca237b74ff969a10d169a5f51b3bcd07a50ac8c5e0ba23",
+ "archive_bytes": 47419,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-tui.tar.gz b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-tui.tar.gz
new file mode 100644
index 0000000..de378e4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http-tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http.tar.gz b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http.tar.gz
new file mode 100644
index 0000000..904f570
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-http.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/cli-tui-check.json b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-tui-check.json
new file mode 100644
index 0000000..e1b39e7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-tui-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "565d32fcccab9dfa10c8af7e21514fb1f4187b0bebac52053db02a6b75bf741f",
+ "archive_bytes": 31726,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/cli-tui.tar.gz b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-tui.tar.gz
new file mode 100644
index 0000000..33a17ee
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/cli-tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/cli.tar.gz b/prototypes/connections/results/2026-09-24-idle-work-binding/cli.tar.gz
new file mode 100644
index 0000000..739dda5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/cli.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/core.json b/prototypes/connections/results/2026-09-24-idle-work-binding/core.json
new file mode 100644
index 0000000..735a4df
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/core.json
@@ -0,0 +1,53 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Release object sections and C bookkeeping, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 6076,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 5156\t 0\t 0\t 5156\t 1424\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "a02135602c3b18129cc9b80cb808994426d0c7869754eac1370c304294ad0be4",
+ "layout_binary_sha256": "db112a9cfd8deed80b9bfbff7628958fdb290cadab1efc7223d8d15ef4c4c389",
+ "budget_sha256": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/default-profile.json b/prototypes/connections/results/2026-09-24-idle-work-binding/default-profile.json
new file mode 100644
index 0000000..a997add
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/default-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35967,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "dfe2b9d03c87eed8cde0d598b182dfc8aa4bba85eca1b64849c77e9c4ef302d3"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 43938,
+ "data": 1068,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "1b7555764d059bca2be05e406d42305dfc68e3fd87813bcfcfaa390945467a8d"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/document-peer-profile.json b/prototypes/connections/results/2026-09-24-idle-work-binding/document-peer-profile.json
new file mode 100644
index 0000000..18dbba5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/document-peer-profile.json
@@ -0,0 +1,23 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-document-peer",
+ "scope": "Review threshold for the explicitly selected authenticated document host on Linux AArch64/GCC 14. Includes linked application code but excludes the shared OpenSSL/libc implementations, process heap, stack, mappings and kernel buffers. Check measured whole-process RSS separately.",
+ "budget_sha256": "defe8efb4d544cdbf615de4d43d4ceba78fc7f1d958f245731202625052eb2ff",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-document-peer": {
+ "sections": {
+ "text": 47038,
+ "data": 1384,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6",
+ "libcrypto.so.3",
+ "libssl.so.3"
+ ],
+ "sha256": "3ec358021988217c212f5527f8947c301f39d6c2022f82c51deff515ce16acbf"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/document-peer.json b/prototypes/connections/results/2026-09-24-idle-work-binding/document-peer.json
new file mode 100644
index 0000000..05c62cc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/document-peer.json
@@ -0,0 +1,16 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 7968,
+ "server_after_large_work_rss_kib": 9712
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/fixed-memory.json b/prototypes/connections/results/2026-09-24-idle-work-binding/fixed-memory.json
new file mode 100644
index 0000000..641bc64
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/fixed-memory.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "fixed-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, the embedded prepared program, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1088,
+ "one_mib_edit_rss_kib": 2128,
+ "one_mib_show_rss_kib": 1088
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "3d2bf30330330ca377d28db0a7d8f4598365c3cfba9c2d43dc5843246fff19b5",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/fixed-profile.json b/prototypes/connections/results/2026-09-24-idle-work-binding/fixed-profile.json
new file mode 100644
index 0000000..6097cdf
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/fixed-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files.",
+ "budget_sha256": "2b7e550992abb1872e52846dec712fab59b78692b776fd7e648d7976299f4b2a",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19404,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "3d2bf30330330ca377d28db0a7d8f4598365c3cfba9c2d43dc5843246fff19b5"
+ },
+ "pure-connections-fixed": {
+ "sections": {
+ "text": 26549,
+ "data": 1028,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "2869469f4c40674c6904729141005c7705bbc5130019d1ce091ffb135bffe60a"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/full-check.json b/prototypes/connections/results/2026-09-24-idle-work-binding/full-check.json
new file mode 100644
index 0000000..0e4d482
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/full-check.json
@@ -0,0 +1,636 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 14227,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 1,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 113,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true,
+ "idle_slot_binding": true
+ },
+ "execution_core_test_sha256": "80aaa8831c44101fc03364d393dd99ac1f3ca3fa861e2561447adad6d965ac0a",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "43bff520b326cfe3f17fa0e0b48efc27e393f6cb7bfff3051fe0115b23e4e5fb",
+ "editor_sha256": "dfe2b9d03c87eed8cde0d598b182dfc8aa4bba85eca1b64849c77e9c4ef302d3",
+ "binary_sha256": "1b7555764d059bca2be05e406d42305dfc68e3fd87813bcfcfaa390945467a8d",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store.c": "44702e9414c26d1ee336b2e36e6713560013c2c8d0091a8900042e2468f88015",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "ead1331794f8e4fb851e21eb7f7d3e7c408316d7481c51996e6ee62a81665a0c",
+ "prototypes/connections/runtime.h": "beff8a8a10f21c017987d69682bb279701d5627227aca60029a711b9e64cca85",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "8c275bf564a674f0f8232026d0d7612df48f10054af75a43af5ed0bce7653e24",
+ "prototypes/connections/server.c": "e8632667de6feaf4d495f87abb159775650e3e4eaf6713b9dfdc5f82807c2bf9",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "f39a7c411afa80812aec6e7a7250cdc833e97cffef8d0cce25d960fe435784f6",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "f9a0c9fa7d0f40d6d72bc72a429dd36e136e27207aa6b0c01df9505d82189b6d",
+ "prototypes/connections/core-layout.c": "e3123bdf74edb99556b05d7cd3a36b6119ec30829541b0ddba2e23e5900b089d",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/package-reproducibility.json b/prototypes/connections/results/2026-09-24-idle-work-binding/package-reproducibility.json
new file mode 100644
index 0000000..d9bb9fe
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/package-reproducibility.json
@@ -0,0 +1,31 @@
+{
+ "profile": "native-package-repeat-build",
+ "same_archive_bytes": "pass",
+ "variants": {
+ "source-cli": {
+ "bytes": 22595,
+ "sha256": "e770e93d15524070b254a46796667e6b0077bc0fa95fbf6ecca051742ec754ca",
+ "runs": 2
+ },
+ "cli": {
+ "bytes": 12987,
+ "sha256": "927e9b0f7bc672e661da0d82abe60aaf3743f6753fbb00e6b39035a3239bae22",
+ "runs": 2
+ },
+ "cli-http": {
+ "bytes": 28719,
+ "sha256": "177bb19c9790712ccb8f75fd65eb59b02c68b526b5155d3b1e83a795c845f031",
+ "runs": 2
+ },
+ "cli-tui": {
+ "bytes": 31726,
+ "sha256": "565d32fcccab9dfa10c8af7e21514fb1f4187b0bebac52053db02a6b75bf741f",
+ "runs": 2
+ },
+ "cli-http-tui": {
+ "bytes": 47419,
+ "sha256": "081e5fe6205760e343ca237b74ff969a10d169a5f51b3bcd07a50ac8c5e0ba23",
+ "runs": 2
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/precompact-budget-failure.txt b/prototypes/connections/results/2026-09-24-idle-work-binding/precompact-budget-failure.txt
new file mode 100644
index 0000000..28b393a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/precompact-budget-failure.txt
@@ -0,0 +1,9 @@
+Before fixed packages switched from strip --strip-debug to strip --strip-unneeded:
+
+python3 package_native.py --fixed --with-tui --output results/2026-09-24-idle-work-binding/cli-tui.tar.gz
+
+package_native.py: error: cli_tui archive grew to 35847 bytes (reviewed maximum 35840); no package was published
+
+This is the captured result on Linux AArch64 with the updated runtime and the
+earlier packaging mode. The final package archive and relocation check are
+cli-tui.tar.gz and cli-tui-check.json in this directory.
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/release.log b/prototypes/connections/results/2026-09-24-idle-work-binding/release.log
new file mode 100644
index 0000000..5c3a893
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/release.log
@@ -0,0 +1,800 @@
+python3 check_core.py --archive build/libpure-execution.a --layout build/core-layout --output "results/2026-09-24-idle-work-binding/core.json"
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Release object sections and C bookkeeping, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 6076,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 5156\t 0\t 0\t 5156\t 1424\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "a02135602c3b18129cc9b80cb808994426d0c7869754eac1370c304294ad0be4",
+ "layout_binary_sha256": "db112a9cfd8deed80b9bfbff7628958fdb290cadab1efc7223d8d15ef4c4c389",
+ "budget_sha256": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror edit.c store.c store-port.c program.c runtime.c evaluate.c -o build/pure-edit
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror server.c store.c store-port.c flow.c program.c runtime.c evaluate.c -o build/pure-connections
+python3 check_profile.py --build build --output "results/2026-09-24-idle-work-binding/default-profile.json"
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35967,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "dfe2b9d03c87eed8cde0d598b182dfc8aa4bba85eca1b64849c77e9c4ef302d3"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 43938,
+ "data": 1068,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "1b7555764d059bca2be05e406d42305dfc68e3fd87813bcfcfaa390945467a8d"
+ }
+ }
+}
+build/pure-compile examples/editor.pure build/embedded-plan.h
+python3 check_profile.py --build build --budget fixed-budget.json --output "results/2026-09-24-idle-work-binding/fixed-profile.json"
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files.",
+ "budget_sha256": "2b7e550992abb1872e52846dec712fab59b78692b776fd7e648d7976299f4b2a",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19404,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "3d2bf30330330ca377d28db0a7d8f4598365c3cfba9c2d43dc5843246fff19b5"
+ },
+ "pure-connections-fixed": {
+ "sections": {
+ "text": 26549,
+ "data": 1028,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "2869469f4c40674c6904729141005c7705bbc5130019d1ce091ffb135bffe60a"
+ }
+ }
+}
+python3 check_micro_memory.py --build build --fixed --output "results/2026-09-24-idle-work-binding/fixed-memory.json"
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "fixed-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, the embedded prepared program, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1088,
+ "one_mib_edit_rss_kib": 2128,
+ "one_mib_show_rss_kib": 1088
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "3d2bf30330330ca377d28db0a7d8f4598365c3cfba9c2d43dc5843246fff19b5",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror test-runtime.c program.c runtime.c evaluate.c store.c store-port.c -o build/test-runtime
+cc -O2 -g -std=c17 -Wall -Wextra -Wpedantic -Werror -DPURE_STORE_TEST test-splice.c program.c runtime.c evaluate.c store.c store-port.c -o build/test-splice
+build/test-flow
+{"transfer":"partial-consumption-and-single-release","storage":"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty"}
+build/test-program
+{"program":"prepare-views-preserve-guards-types-effects-and-atomic-install","boundary_semantic_comparisons":3584}
+build/test-fields
+{"fields":"named-layouts-unaligned-u32le-tail-dynamic-ranges-aliases-failures-limits","data_boundary_cases":48}
+python3 check.py --server build/pure-connections --runtime-test build/test-runtime --splice-test build/test-splice --editor build/pure-edit --store-source store.c --output "results/2026-09-24-idle-work-binding/full-check.json"
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 14227,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 1,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 113,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true,
+ "idle_slot_binding": true
+ },
+ "execution_core_test_sha256": "80aaa8831c44101fc03364d393dd99ac1f3ca3fa861e2561447adad6d965ac0a",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "43bff520b326cfe3f17fa0e0b48efc27e393f6cb7bfff3051fe0115b23e4e5fb",
+ "editor_sha256": "dfe2b9d03c87eed8cde0d598b182dfc8aa4bba85eca1b64849c77e9c4ef302d3",
+ "binary_sha256": "1b7555764d059bca2be05e406d42305dfc68e3fd87813bcfcfaa390945467a8d",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store.c": "44702e9414c26d1ee336b2e36e6713560013c2c8d0091a8900042e2468f88015",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "ead1331794f8e4fb851e21eb7f7d3e7c408316d7481c51996e6ee62a81665a0c",
+ "prototypes/connections/runtime.h": "beff8a8a10f21c017987d69682bb279701d5627227aca60029a711b9e64cca85",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "8c275bf564a674f0f8232026d0d7612df48f10054af75a43af5ed0bce7653e24",
+ "prototypes/connections/server.c": "e8632667de6feaf4d495f87abb159775650e3e4eaf6713b9dfdc5f82807c2bf9",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "f39a7c411afa80812aec6e7a7250cdc833e97cffef8d0cce25d960fe435784f6",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "f9a0c9fa7d0f40d6d72bc72a429dd36e136e27207aa6b0c01df9505d82189b6d",
+ "prototypes/connections/core-layout.c": "e3123bdf74edb99556b05d7cd3a36b6119ec30829541b0ddba2e23e5900b089d",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
+python3 check_micro_memory.py --build build --output "results/2026-09-24-idle-work-binding/source-memory.json"
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "source-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1056,
+ "one_mib_edit_rss_kib": 2080,
+ "one_mib_show_rss_kib": 1056
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "dfe2b9d03c87eed8cde0d598b182dfc8aa4bba85eca1b64849c77e9c4ef302d3",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/runtime-sanitized.json b/prototypes/connections/results/2026-09-24-idle-work-binding/runtime-sanitized.json
new file mode 100644
index 0000000..0c1b5b0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/runtime-sanitized.json
@@ -0,0 +1 @@
+{"runtime_tests":"passed","domain_bytes":200,"work_slot_bytes":224,"ticket_bytes":24,"prepared_program_bytes":680,"forwarding_chain":1024,"native_storage_pipeline":true,"idle_slot_binding":true}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/service-scale.json b/prototypes/connections/results/2026-09-24-idle-work-binding/service-scale.json
new file mode 100644
index 0000000..b0fe27b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/service-scale.json
@@ -0,0 +1,100 @@
+{
+ "profile": "document-app-many-objects-concurrent-clients",
+ "documents_per_variant": 1024,
+ "clients": 8,
+ "body_bytes": 8192,
+ "operations_per_variant": 4096,
+ "server_budget_bytes": 1048576,
+ "peak_rss_limit_kib": 4096,
+ "same_final_documents": "pass",
+ "fixed": {
+ "binary_sha256": "2869469f4c40674c6904729141005c7705bbc5130019d1ce091ffb135bffe60a",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1504,
+ "peak_rss_kib": 1680,
+ "idle_vm_kib": 2448,
+ "peak_vm_kib": 2528,
+ "idle_threads": 1,
+ "peak_threads": 1,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49184,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 390209,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 40848
+ }
+ },
+ "source": {
+ "binary_sha256": "1b7555764d059bca2be05e406d42305dfc68e3fd87813bcfcfaa390945467a8d",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1552,
+ "peak_rss_kib": 1728,
+ "idle_vm_kib": 2464,
+ "peak_vm_kib": 2528,
+ "idle_threads": 1,
+ "peak_threads": 1,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49184,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 442020,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 41528
+ }
+ },
+ "source_async": {
+ "binary_sha256": "9485151b8902d66052bb689e821b502810b66561e0a251d3ce091c4919b7c67e",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1600,
+ "peak_rss_kib": 1776,
+ "idle_vm_kib": 2864,
+ "peak_vm_kib": 2944,
+ "idle_threads": 3,
+ "peak_threads": 3,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 40993,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 270839,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 43320
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/source-cli-check.json b/prototypes/connections/results/2026-09-24-idle-work-binding/source-cli-check.json
new file mode 100644
index 0000000..729710b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/source-cli-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "e770e93d15524070b254a46796667e6b0077bc0fa95fbf6ecca051742ec754ca",
+ "archive_bytes": 22595,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/source-cli.tar.gz b/prototypes/connections/results/2026-09-24-idle-work-binding/source-cli.tar.gz
new file mode 100644
index 0000000..4981e60
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/source-cli.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/source-memory.json b/prototypes/connections/results/2026-09-24-idle-work-binding/source-memory.json
new file mode 100644
index 0000000..aa663a6
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/source-memory.json
@@ -0,0 +1,15 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "variant": "source-program",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1056,
+ "one_mib_edit_rss_kib": 2080,
+ "one_mib_show_rss_kib": 1056
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "dfe2b9d03c87eed8cde0d598b182dfc8aa4bba85eca1b64849c77e9c4ef302d3",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/tui-profile.json b/prototypes/connections/results/2026-09-24-idle-work-binding/tui-profile.json
new file mode 100644
index 0000000..ead0b8f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/tui-profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app, including the bounded document browser. The raised text ceiling reviews its measured 2,541-byte addition; default CLI and core ceilings are unchanged. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS, including 1,024-key browsing, is checked by check_tui.py on the recorded Linux AArch64 host.",
+ "budget_sha256": "4d3097c9ec3c0139cbdd82161a74d610c15d31c6ee5625101410627664f925e7",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "sections": {
+ "text": 31463,
+ "data": 1036,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "297acfbeee36de36f4651e3ae5438c8a91604d97be9bc753fe2af380887b8693"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-idle-work-binding/tui.json b/prototypes/connections/results/2026-09-24-idle-work-binding/tui.json
new file mode 100644
index 0000000..d482848
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-idle-work-binding/tui.json
@@ -0,0 +1,22 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, resized and last key opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1808,
+ "one_mib_peak_rss_kib": 2832,
+ "one_thousand_key_list_peak_rss_kib": 1888,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "297acfbeee36de36f4651e3ae5438c8a91604d97be9bc753fe2af380887b8693"
+}
diff --git a/prototypes/connections/results/2026-09-24-in-process-routing/mirror-ext4.json b/prototypes/connections/results/2026-09-24-in-process-routing/mirror-ext4.json
new file mode 100644
index 0000000..0b1454e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-in-process-routing/mirror-ext4.json
@@ -0,0 +1,56 @@
+{
+ "passed": true,
+ "source_body_sha256": "06cb5e32505f66804f6e8c79e3230105ca4769444e1389ee36f6f11fd61f2d3a",
+ "mirror_sha256": "3c22ef868198f805f4cd1fe7c9c55b69f32c599f5076444f9af4f1297cb874e2",
+ "editor_sha256": "04974e2d3c4d7f5fb22aff67e7399aa2ebcbd85eb24da0c0e41f3ef047d5ddec",
+ "source_one_mib_to_two_domains": {
+ "source_revision": "1",
+ "bytes": 1048576,
+ "targets": [
+ {
+ "index": 0,
+ "status": "ok",
+ "revision": "1"
+ },
+ {
+ "index": 1,
+ "status": "ok",
+ "revision": "1"
+ }
+ ]
+ },
+ "independent_partial_conflict": {
+ "source_revision": "2",
+ "bytes": 1048576,
+ "targets": [
+ {
+ "index": 0,
+ "status": "ok",
+ "revision": "2"
+ },
+ {
+ "index": 1,
+ "status": "conflict",
+ "revision": "1"
+ }
+ ]
+ },
+ "conflict_recovered_revision": "2",
+ "empty_body_forwarded": true,
+ "target_budget_checked_before_document_write": true,
+ "all_admissions_before_document_writes": true,
+ "source_failure_before_target_creation": true,
+ "one_mib_two_target_peak_rss": {
+ "exit_code": 0,
+ "max_rss_kib": 2144,
+ "raw_max_rss": 2144,
+ "raw_unit": "KiB"
+ },
+ "one_mib_eight_targets_verified": true,
+ "one_mib_eight_target_peak_rss": {
+ "exit_code": 0,
+ "max_rss_kib": 2144,
+ "raw_max_rss": 2144,
+ "raw_unit": "KiB"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-in-process-routing/mirror-sanitized.json b/prototypes/connections/results/2026-09-24-in-process-routing/mirror-sanitized.json
new file mode 100644
index 0000000..12f3550
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-in-process-routing/mirror-sanitized.json
@@ -0,0 +1,46 @@
+{
+ "passed": true,
+ "source_body_sha256": "06cb5e32505f66804f6e8c79e3230105ca4769444e1389ee36f6f11fd61f2d3a",
+ "mirror_sha256": "0c25b281c3b746f74a451bb3eefb2345c98f3ba01a08d5751347246f5bc48ee1",
+ "editor_sha256": "6d0b6b2b06ed25e0fc0db229091d19fe56de01bae5f5a25c72ee228589412541",
+ "source_one_mib_to_two_domains": {
+ "source_revision": "1",
+ "bytes": 1048576,
+ "targets": [
+ {
+ "index": 0,
+ "status": "ok",
+ "revision": "1"
+ },
+ {
+ "index": 1,
+ "status": "ok",
+ "revision": "1"
+ }
+ ]
+ },
+ "independent_partial_conflict": {
+ "source_revision": "2",
+ "bytes": 1048576,
+ "targets": [
+ {
+ "index": 0,
+ "status": "ok",
+ "revision": "2"
+ },
+ {
+ "index": 1,
+ "status": "conflict",
+ "revision": "1"
+ }
+ ]
+ },
+ "conflict_recovered_revision": "2",
+ "empty_body_forwarded": true,
+ "target_budget_checked_before_document_write": true,
+ "all_admissions_before_document_writes": true,
+ "source_failure_before_target_creation": true,
+ "one_mib_two_target_peak_rss": null,
+ "one_mib_eight_targets_verified": true,
+ "one_mib_eight_target_peak_rss": null
+}
diff --git a/prototypes/connections/results/2026-09-24-in-process-routing/mirror-tmp.json b/prototypes/connections/results/2026-09-24-in-process-routing/mirror-tmp.json
new file mode 100644
index 0000000..01f80dd
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-in-process-routing/mirror-tmp.json
@@ -0,0 +1,56 @@
+{
+ "passed": true,
+ "source_body_sha256": "06cb5e32505f66804f6e8c79e3230105ca4769444e1389ee36f6f11fd61f2d3a",
+ "mirror_sha256": "3c22ef868198f805f4cd1fe7c9c55b69f32c599f5076444f9af4f1297cb874e2",
+ "editor_sha256": "04974e2d3c4d7f5fb22aff67e7399aa2ebcbd85eb24da0c0e41f3ef047d5ddec",
+ "source_one_mib_to_two_domains": {
+ "source_revision": "1",
+ "bytes": 1048576,
+ "targets": [
+ {
+ "index": 0,
+ "status": "ok",
+ "revision": "1"
+ },
+ {
+ "index": 1,
+ "status": "ok",
+ "revision": "1"
+ }
+ ]
+ },
+ "independent_partial_conflict": {
+ "source_revision": "2",
+ "bytes": 1048576,
+ "targets": [
+ {
+ "index": 0,
+ "status": "ok",
+ "revision": "2"
+ },
+ {
+ "index": 1,
+ "status": "conflict",
+ "revision": "1"
+ }
+ ]
+ },
+ "conflict_recovered_revision": "2",
+ "empty_body_forwarded": true,
+ "target_budget_checked_before_document_write": true,
+ "all_admissions_before_document_writes": true,
+ "source_failure_before_target_creation": true,
+ "one_mib_two_target_peak_rss": {
+ "exit_code": 0,
+ "max_rss_kib": 2128,
+ "raw_max_rss": 2128,
+ "raw_unit": "KiB"
+ },
+ "one_mib_eight_targets_verified": true,
+ "one_mib_eight_target_peak_rss": {
+ "exit_code": 0,
+ "max_rss_kib": 2128,
+ "raw_max_rss": 2128,
+ "raw_unit": "KiB"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-micro-default/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-micro-default/pure-source-preview.tar.gz
new file mode 100644
index 0000000..20674be
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-default/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-micro-default/source-package-check.json b/prototypes/connections/results/2026-09-24-micro-default/source-package-check.json
new file mode 100644
index 0000000..bfd1940
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-default/source-package-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "26bdd3f8768bc5c66c282f989026ac4d9de64398ed3c31e6dc8abbc3d84491d0",
+ "archive_bytes": 338097,
+ "source_files": 173,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean default build contains only the core, parser-free CLI and its build-time compiler",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-micro-package-boundary/cli-check.json b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli-check.json
new file mode 100644
index 0000000..da74f01
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "3e5b064bbf81b13be24494a5d5a9bd55fa5ea057d2d5614965f3e5556babf9ab",
+ "archive_bytes": 14692,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-micro-package-boundary/cli.tar.gz b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli.tar.gz
new file mode 100644
index 0000000..7467329
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http-check.json b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http-check.json
new file mode 100644
index 0000000..1d8281a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "d7f35c8add62551bfaf9819e4edd64b8b3f25dc084b2c519d172d4344f66b160",
+ "archive_bytes": 32548,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http.tar.gz b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http.tar.gz
new file mode 100644
index 0000000..4ce4a1a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http_tui-check.json b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http_tui-check.json
new file mode 100644
index 0000000..e247b61
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http_tui-check.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "6dc051ebc74eaf460c97e7259d0d408b2424ae4cfd19078a4227e12a1382faef",
+ "archive_bytes": 51424,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http_tui.tar.gz b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http_tui.tar.gz
new file mode 100644
index 0000000..529f2b6
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_http_tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_tui-check.json b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_tui-check.json
new file mode 100644
index 0000000..769e922
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_tui-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "daf25aaf480559f4b9cfffa13ce91dcf1b84f008f0323ea59d00566dcfdc5d89",
+ "archive_bytes": 33761,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_tui.tar.gz b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_tui.tar.gz
new file mode 100644
index 0000000..905c339
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-package-boundary/cli_tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-micro-profile/default-host-budget.json b/prototypes/connections/results/2026-09-24-micro-profile/default-host-budget.json
new file mode 100644
index 0000000..9ea33b6
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-micro-profile/default-host-budget.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35807,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 42761,
+ "data": 1040,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-mirror-source/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-mirror-source/pure-source-preview.tar.gz
new file mode 100644
index 0000000..7f3ea7a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-mirror-source/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-mirror-source/source-check-linux-aarch64.json b/prototypes/connections/results/2026-09-24-mirror-source/source-check-linux-aarch64.json
new file mode 100644
index 0000000..8fdefbb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-mirror-source/source-check-linux-aarch64.json
@@ -0,0 +1,15 @@
+{
+ "archive_sha256": "7da3049ad80d1f54770524ba04583b5e2aef2e59e6d252d347947d32e7327f0b",
+ "archive_bytes": 332792,
+ "source_files": 170,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean selected page store exports mixed revisions to the default flat store",
+ "clean one-MiB document fans out to two same-process Pure domains with independent conflict and release",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan-final.json b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan-final.json
new file mode 100644
index 0000000..253130f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan-final.json
@@ -0,0 +1 @@
+{"cli_conflict_preserves_draft": "pass", "definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 135936, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan-repeated.json b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan-repeated.json
new file mode 100644
index 0000000..541ec3e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan-repeated.json
@@ -0,0 +1 @@
+{"cli_conflict_preserves_draft": "pass", "definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_rss_samples_kib": [362224, 385120], "large_window_rss_kib": 118016, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan.json b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan.json
new file mode 100644
index 0000000..605d189
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-asan.json
@@ -0,0 +1 @@
+{"cli_conflict_preserves_draft": "pass", "definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 142944, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow-final.json b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow-final.json
new file mode 100644
index 0000000..4365549
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow-final.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 43936, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow-repeated.json b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow-repeated.json
new file mode 100644
index 0000000..7d36eca
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow-repeated.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_rss_samples_kib": [46672, 48960], "large_window_rss_kib": 43952, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow.json b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow.json
new file mode 100644
index 0000000..4f6d78b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/gtk-flow.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 43952, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/hybrid-gtk-flow.json b/prototypes/connections/results/2026-09-24-multi-document-window/hybrid-gtk-flow.json
new file mode 100644
index 0000000..8d132e5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/hybrid-gtk-flow.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 44032, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/legacy-package-recheck.json b/prototypes/connections/results/2026-09-24-multi-document-window/legacy-package-recheck.json
new file mode 100644
index 0000000..dcae905
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/legacy-package-recheck.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "b72bc0b5321fa6efcc0ca8fbc3e328bc220333b0af134b1e75b7c5b517999a72",
+ "archive_bytes": 48934,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted archived GTK window edits the same document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/legacy-package-repeated.json b/prototypes/connections/results/2026-09-24-multi-document-window/legacy-package-repeated.json
new file mode 100644
index 0000000..dcae905
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/legacy-package-repeated.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "b72bc0b5321fa6efcc0ca8fbc3e328bc220333b0af134b1e75b7c5b517999a72",
+ "archive_bytes": 48934,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted archived GTK window edits the same document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/package-final.json b/prototypes/connections/results/2026-09-24-multi-document-window/package-final.json
new file mode 100644
index 0000000..fd4343a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/package-final.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "59a5110ef5dd186c7ba9e5c3fbe74217c10c98014c2823aabf141d3f354f8dd6",
+ "archive_bytes": 49746,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted GTK window switches documents without losing drafts"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/package-repeated.json b/prototypes/connections/results/2026-09-24-multi-document-window/package-repeated.json
new file mode 100644
index 0000000..fd4343a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/package-repeated.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "59a5110ef5dd186c7ba9e5c3fbe74217c10c98014c2823aabf141d3f354f8dd6",
+ "archive_bytes": 49746,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted GTK window switches documents without losing drafts"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/package.json b/prototypes/connections/results/2026-09-24-multi-document-window/package.json
new file mode 100644
index 0000000..9616e80
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/package.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "40b7fef5e3202840794c91c5eb9c7e5592244dab443ce3597cc6fb9745b97746",
+ "archive_bytes": 49722,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted GTK window and selected external host edit the same document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/pure-document-window-final-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-multi-document-window/pure-document-window-final-linux-aarch64.tar.gz
new file mode 100644
index 0000000..ded86dd
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/pure-document-window-final-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/pure-document-window-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-multi-document-window/pure-document-window-linux-aarch64.tar.gz
new file mode 100644
index 0000000..1633c3d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/pure-document-window-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-fresh-buffer.json b/prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-fresh-buffer.json
new file mode 100644
index 0000000..0e0b7be
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-fresh-buffer.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_rss_samples_kib": [48416, 49472, 51216, 52208, 54176, 55504, 57728, 59568], "large_window_rss_kib": 43968, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-initial.json b/prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-initial.json
new file mode 100644
index 0000000..71658ed
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/switch-memory-initial.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_rss_samples_kib": [47328, 48048, 49888, 51744, 53840, 55824, 56864, 58752], "large_window_rss_kib": 43920, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-multi-document-window/window-profile.json b/prototypes/connections/results/2026-09-24-multi-document-window/window-profile.json
new file mode 100644
index 0000000..d47571f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-multi-document-window/window-profile.json
@@ -0,0 +1,25 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-native-document-authoring",
+ "scope": "Review ceiling for the selected GTK document-and-definition host on Linux AArch64/GCC 14. Linked code sections and direct dependencies only; the measured 44 MiB whole-process RSS and shared GTK stack remain separate costs.",
+ "budget_sha256": "27ee292bf3fe9a15d27942f64cff01dfccde0ef5054acbb53faf76208d89d110",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-window": {
+ "sections": {
+ "text": 49882,
+ "data": 1504,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6",
+ "libgio-2.0.so.0",
+ "libglib-2.0.so.0",
+ "libgobject-2.0.so.0",
+ "libgtk-4.so.1"
+ ],
+ "sha256": "4d9806ce6f82413d17bc93452d9fd3bcc2b18272d15a2edaf81f8888e73b4e02"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-native-checkpoint/fixed-memory.json b/prototypes/connections/results/2026-09-24-native-checkpoint/fixed-memory.json
new file mode 100644
index 0000000..84c7eb4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-checkpoint/fixed-memory.json
@@ -0,0 +1,43 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "portable-measurement-no-budget",
+ "variant": "fixed-program",
+ "scope": "Child-process peak RSS for native CLI document creation, read and one-byte revision edit; includes libc and the selected program form, excludes filesystem cache, kernel buffers, TLS, GUI and other apps. No cross-platform memory ceiling is asserted.",
+ "samples": {
+ "small_edit_rss_kib": 1104,
+ "one_mib_edit_rss_kib": 2128,
+ "one_mib_show_rss_kib": 1072,
+ "one_mib_splice_rss_kib": 1104
+ },
+ "raw_samples": {
+ "small_edit_rss_kib": {
+ "exit_code": 0,
+ "max_rss_kib": 1104,
+ "raw_max_rss": 1104,
+ "raw_unit": "KiB"
+ },
+ "one_mib_edit_rss_kib": {
+ "exit_code": 0,
+ "max_rss_kib": 2128,
+ "raw_max_rss": 2128,
+ "raw_unit": "KiB"
+ },
+ "one_mib_show_rss_kib": {
+ "exit_code": 0,
+ "max_rss_kib": 1072,
+ "raw_max_rss": 1072,
+ "raw_unit": "KiB"
+ },
+ "one_mib_splice_rss_kib": {
+ "exit_code": 0,
+ "max_rss_kib": 1104,
+ "raw_max_rss": 1104,
+ "raw_unit": "KiB"
+ }
+ },
+ "budget_sha256": null,
+ "binary_sha256": "435e087adf62253078678b42c169426adcaddd514c78717e3be570f88dbcc248",
+ "binary_bytes": 135344,
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-checkpoint/fixed-tui.json b/prototypes/connections/results/2026-09-24-native-checkpoint/fixed-tui.json
new file mode 100644
index 0000000..05a5d34
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-checkpoint/fixed-tui.json
@@ -0,0 +1,24 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": null,
+ "one_mib_peak_rss_kib": null,
+ "one_thousand_key_list_peak_rss_kib": null,
+ "one_mib_peak_rss_limit_kib": 0,
+ "portable": true,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "d49431543f233d7979a3cdc07ec2c9e938acf014df6257f0165f76f30a0e248c"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-checkpoint/source-memory.json b/prototypes/connections/results/2026-09-24-native-checkpoint/source-memory.json
new file mode 100644
index 0000000..3f45eb1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-checkpoint/source-memory.json
@@ -0,0 +1,43 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "portable-measurement-no-budget",
+ "variant": "source-program",
+ "scope": "Child-process peak RSS for native CLI document creation, read and one-byte revision edit; includes libc and the selected program form, excludes filesystem cache, kernel buffers, TLS, GUI and other apps. No cross-platform memory ceiling is asserted.",
+ "samples": {
+ "small_edit_rss_kib": 1056,
+ "one_mib_edit_rss_kib": 2080,
+ "one_mib_show_rss_kib": 1056,
+ "one_mib_splice_rss_kib": 1104
+ },
+ "raw_samples": {
+ "small_edit_rss_kib": {
+ "exit_code": 0,
+ "max_rss_kib": 1056,
+ "raw_max_rss": 1056,
+ "raw_unit": "KiB"
+ },
+ "one_mib_edit_rss_kib": {
+ "exit_code": 0,
+ "max_rss_kib": 2080,
+ "raw_max_rss": 2080,
+ "raw_unit": "KiB"
+ },
+ "one_mib_show_rss_kib": {
+ "exit_code": 0,
+ "max_rss_kib": 1056,
+ "raw_max_rss": 1056,
+ "raw_unit": "KiB"
+ },
+ "one_mib_splice_rss_kib": {
+ "exit_code": 0,
+ "max_rss_kib": 1104,
+ "raw_max_rss": 1104,
+ "raw_unit": "KiB"
+ }
+ },
+ "budget_sha256": null,
+ "binary_sha256": "23ebc0ce1df9c49216511bee658fd5b9e373509e296bd2c2f8e76e6d3081cded",
+ "binary_bytes": 178336,
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-checkpoint/source-tui.json b/prototypes/connections/results/2026-09-24-native-checkpoint/source-tui.json
new file mode 100644
index 0000000..0e2c5ad
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-checkpoint/source-tui.json
@@ -0,0 +1,27 @@
+{
+ "profile": "native-source-document-terminal-editor",
+ "checks": [
+ "source parse and incompatible definitions fail before store creation",
+ "source CLI and TUI read the same document",
+ "changed source field layout drives TUI input encoding",
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": null,
+ "one_mib_peak_rss_kib": null,
+ "one_thousand_key_list_peak_rss_kib": null,
+ "one_mib_peak_rss_limit_kib": 0,
+ "portable": true,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "8e5ac649f2ab9a4dec02d32153f70aa13d97266cca1c9a942ba8fba27d04c8cf"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/full-package-check.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/full-package-check.json
new file mode 100644
index 0000000..05264e9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/full-package-check.json
@@ -0,0 +1,20 @@
+{
+ "archive_sha256": "831b049f8f4c38bc219bab7cd50138da862593e1e1c768b16705816438cac95f",
+ "archive_bytes": 100900,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-connections",
+ "pure-document-peer",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted HTTP host updates the same document as the native CLI",
+ "extracted C/Python TLS peers share a 1 MiB document and recover",
+ "extracted GTK window and selected external host edit the same document"
+ ],
+ "peer_idle_rss_kib": 7840,
+ "peer_after_large_work_rss_kib": 9520
+}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-flow-final.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-flow-final.json
new file mode 100644
index 0000000..4bac323
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-flow-final.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 43792, "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-flow.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-flow.json
new file mode 100644
index 0000000..3372af3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-flow.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 44032, "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-sanitized-final.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-sanitized-final.json
new file mode 100644
index 0000000..b65d2a2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-sanitized-final.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 147696, "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-sanitized.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-sanitized.json
new file mode 100644
index 0000000..fe540f2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/gtk-sanitized.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 147952, "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/http-only-package-check.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/http-only-package-check.json
new file mode 100644
index 0000000..06ca49e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/http-only-package-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "a6c81aaf7ffef0cf1604e727f318d40bd51989ccb4b350793723ad3434d49148",
+ "archive_bytes": 47527,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-connections"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted HTTP host updates the same document as the native CLI"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/micro-memory.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/micro-memory.json
new file mode 100644
index 0000000..2bf6a8d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/micro-memory.json
@@ -0,0 +1,14 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1056,
+ "one_mib_edit_rss_kib": 2080,
+ "one_mib_show_rss_kib": 1104
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/micro-package-check.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/micro-package-check.json
new file mode 100644
index 0000000..12dc47f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/micro-package-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "b010450dfe11be3196e6b57071f9ac6b79e1fd79d5d5b2a314ea8780096ad7c6",
+ "archive_bytes": 22482,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/peer-only-package-check.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/peer-only-package-check.json
new file mode 100644
index 0000000..acf8029
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/peer-only-package-check.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "18a171c2f1a7b75f4fe030d6a087d6c2f3471fca731e2c9d7f103940315852e5",
+ "archive_bytes": 49186,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-document-peer"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted C/Python TLS peers share a 1 MiB document and recover"
+ ],
+ "peer_idle_rss_kib": 7840,
+ "peer_after_large_work_rss_kib": 9520
+}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-authoring-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-authoring-linux-aarch64.tar.gz
new file mode 100644
index 0000000..0e64e74
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-authoring-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-http-only-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-http-only-linux-aarch64.tar.gz
new file mode 100644
index 0000000..3c32eb4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-http-only-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-micro-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-micro-linux-aarch64.tar.gz
new file mode 100644
index 0000000..9b3fddc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-micro-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-peer-only-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-peer-only-linux-aarch64.tar.gz
new file mode 100644
index 0000000..d2b11d3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-peer-only-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-window-only-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-window-only-linux-aarch64.tar.gz
new file mode 100644
index 0000000..911348b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/pure-document-window-only-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/window-authoring.png b/prototypes/connections/results/2026-09-24-native-definition-authoring/window-authoring.png
new file mode 100644
index 0000000..9a7945c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/window-authoring.png
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/window-budget.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/window-budget.json
new file mode 100644
index 0000000..547b408
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/window-budget.json
@@ -0,0 +1,25 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-native-document-authoring",
+ "scope": "Review ceiling for the selected GTK document-and-definition host on Linux AArch64/GCC 14. Linked code sections and direct dependencies only; the measured 44 MiB whole-process RSS and shared GTK stack remain separate costs.",
+ "budget_sha256": "27ee292bf3fe9a15d27942f64cff01dfccde0ef5054acbb53faf76208d89d110",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-window": {
+ "sections": {
+ "text": 48247,
+ "data": 1456,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6",
+ "libgio-2.0.so.0",
+ "libglib-2.0.so.0",
+ "libgobject-2.0.so.0",
+ "libgtk-4.so.1"
+ ],
+ "sha256": "b16b34dfb1b05bf6437b022992fa185787631734f76043149c410b0caf165895"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-native-definition-authoring/window-only-package-check.json b/prototypes/connections/results/2026-09-24-native-definition-authoring/window-only-package-check.json
new file mode 100644
index 0000000..f0fa500
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-definition-authoring/window-only-package-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "b72bc0b5321fa6efcc0ca8fbc3e328bc220333b0af134b1e75b7c5b517999a72",
+ "archive_bytes": 48934,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted GTK window and selected external host edit the same document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/build.json b/prototypes/connections/results/2026-09-24-native-document-window/build.json
new file mode 100644
index 0000000..52bcb73
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/build.json
@@ -0,0 +1,16 @@
+{
+ "host": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "compiler": "cc (Debian 14.2.0-19) 14.2.0",
+ "gtk": "4.18.6",
+ "binary_sha256": {
+ "build/pure-edit": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03",
+ "build/pure-connections": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f",
+ "build/pure-edit-window": "97b12dbfb3af430bb13547d4d0f7791ab35a265fe9e22ca6265c1b4ec5d3165f"
+ },
+ "sources": {
+ "edit-window.c": "b96687857e2fd66fc25d5ba8e3d91f06a3eae060a4161c30259174c15ee13603",
+ "check_window.py": "208cc9bb56123c7db0596dd1c97c6da0026f3bc9f0bb9f545f2cbb1acf30b712",
+ "Makefile": "d7fb2dce9f4b6854207eeb8b6b6e8b2dc294c6c1faf18bf3f486344834fae6d2",
+ "examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/connection-check.json b/prototypes/connections/results/2026-09-24-native-document-window/connection-check.json
new file mode 100644
index 0000000..221db03
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/connection-check.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 41,
+ "commits": 12,
+ "gets": 14,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 31,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115416,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "07c328c98769d02d544aea2fc5389048a7620c00d9b3ea49b9c7ba45e33984b1",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "0e4ec2c78334af2056af376a6ba9aef7416a34c6d4fbd9082f4abb640e6de28c",
+ "editor_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03",
+ "binary_sha256": "e76d4c0a721c9ceb7142db0edbaa1f5c44bd78a2c55029658109c83e8076875f",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.c": "44702e9414c26d1ee336b2e36e6713560013c2c8d0091a8900042e2468f88015",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "5d08639b5a71572553bda47cbd35562805d601aaa81f20731cd9154768ec025e",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "e1735316769b4ce4d5904b9587ccfa3ebeafa26517c53dba4491191d58c97b8e",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "0cb23dd0cff6bd0c9dc154f6f9ec253af72a23d93bf1a3797cd45ddd6091c9d0",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/core-budget.json b/prototypes/connections/results/2026-09-24-native-document-window/core-budget.json
new file mode 100644
index 0000000..8c0caf7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/core-budget.json
@@ -0,0 +1,53 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Release object sections and C bookkeeping, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 5932,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 5012\t 0\t 0\t 5012\t 1394\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "d56c50e38c6c0949cfad069d34568da2ac45b1d60097cf9e7c4bf804f44c8128",
+ "layout_binary_sha256": "47cf1803007fc1ec85f119bd46195ad39d9f01ef0146bf5cc45e1af31eb18098",
+ "budget_sha256": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/dependencies.txt b/prototypes/connections/results/2026-09-24-native-document-window/dependencies.txt
new file mode 100644
index 0000000..e61b79d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/dependencies.txt
@@ -0,0 +1,10 @@
+pure-edit
+0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
+pure-connections
+0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
+pure-edit-window
+0x0000000000000001 (NEEDED) Shared library: [libgtk-4.so.1]
+0x0000000000000001 (NEEDED) Shared library: [libgio-2.0.so.0]
+0x0000000000000001 (NEEDED) Shared library: [libgobject-2.0.so.0]
+0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
+0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/gtk-flow.json b/prototypes/connections/results/2026-09-24-native-document-window/gtk-flow.json
new file mode 100644
index 0000000..1e4aa66
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/gtk-flow.json
@@ -0,0 +1 @@
+{"empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "large_window_rss_kib": 44208, "one_mib_document_one_byte_edit": "pass", "profile": "optional-native-document-window", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/gtk-sanitized.json b/prototypes/connections/results/2026-09-24-native-document-window/gtk-sanitized.json
new file mode 100644
index 0000000..babeafb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/gtk-sanitized.json
@@ -0,0 +1 @@
+{"empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "large_window_rss_kib": 143168, "one_mib_document_one_byte_edit": "pass", "profile": "optional-native-document-window", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/size.txt b/prototypes/connections/results/2026-09-24-native-document-window/size.txt
new file mode 100644
index 0000000..dc609de
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/size.txt
@@ -0,0 +1,6 @@
+ text data bss dec hex filename
+ 5012 0 0 5012 1394 runtime.o (ex prototypes/connections/build/libpure-execution.a)
+ 920 0 0 920 398 evaluate.o (ex prototypes/connections/build/libpure-execution.a)
+ 35807 944 16 36767 8f9f prototypes/connections/build/pure-edit
+ 42761 1040 16 43817 ab29 prototypes/connections/build/pure-connections
+ 43308 1376 16 44700 ae9c prototypes/connections/build/pure-edit-window
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/stripped.txt b/prototypes/connections/results/2026-09-24-native-document-window/stripped.txt
new file mode 100644
index 0000000..6eb0197
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/stripped.txt
@@ -0,0 +1,3 @@
+pure-edit elf_bytes=177384 stripped_bytes=67904
+pure-connections elf_bytes=199080 stripped_bytes=68000
+pure-edit-window elf_bytes=199184 stripped_bytes=68280
diff --git a/prototypes/connections/results/2026-09-24-native-document-window/window.png b/prototypes/connections/results/2026-09-24-native-document-window/window.png
new file mode 100644
index 0000000..809f57a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-document-window/window.png
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-save/fixed-cli-package-check.json b/prototypes/connections/results/2026-09-24-native-save/fixed-cli-package-check.json
new file mode 100644
index 0000000..8e62057
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/fixed-cli-package-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "2f491df77c2d5c39c838f7235bcfcaadbd89b981e5b40624e624553a74604421",
+ "archive_bytes": 12966,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-native-save/fixed-package-check.json b/prototypes/connections/results/2026-09-24-native-save/fixed-package-check.json
new file mode 100644
index 0000000..97dafe5
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/fixed-package-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "629dca525ec849fe9ab822ca5ff931477438534235ab00f7d34f873ee18b41e7",
+ "archive_bytes": 32072,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-native-save/flat-fixed-tui.json b/prototypes/connections/results/2026-09-24-native-save/flat-fixed-tui.json
new file mode 100644
index 0000000..97fb4d7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/flat-fixed-tui.json
@@ -0,0 +1,24 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1808,
+ "one_mib_peak_rss_kib": 2832,
+ "one_thousand_key_list_peak_rss_kib": 1856,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "portable": false,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "e8b224e3ce5f5d83d597418d4027ec36dd44bfe84d17f6e9224135dc457316c1"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-save/flat-package-check.json b/prototypes/connections/results/2026-09-24-native-save/flat-package-check.json
new file mode 100644
index 0000000..f3db134
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/flat-package-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "0f8d1620cf36c968174687e7ca350d97d8f3101ce38bb70239b673ab104fe6f6",
+ "archive_bytes": 51117,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-tui"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "relocated source-loaded TUI and CLI share UTF-8, large and many-document paths"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-native-save/flat-source-tui.json b/prototypes/connections/results/2026-09-24-native-save/flat-source-tui.json
new file mode 100644
index 0000000..aa7d0b9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/flat-source-tui.json
@@ -0,0 +1,27 @@
+{
+ "profile": "native-source-document-terminal-editor",
+ "checks": [
+ "source parse and incompatible definitions fail before store creation",
+ "source CLI and TUI read the same document",
+ "changed source field layout drives TUI input encoding",
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1824,
+ "one_mib_peak_rss_kib": 3216,
+ "one_thousand_key_list_peak_rss_kib": 1936,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "portable": false,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "46bdfde2b8997213bf69c612bd63913330859fd46d77ecb9b7fca99e552ee143"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-save/hybrid-fixed-tui.json b/prototypes/connections/results/2026-09-24-native-save/hybrid-fixed-tui.json
new file mode 100644
index 0000000..5b5e97c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/hybrid-fixed-tui.json
@@ -0,0 +1,24 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1840,
+ "one_mib_peak_rss_kib": 3184,
+ "one_thousand_key_list_peak_rss_kib": 1904,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "portable": false,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "09303ec33d07c12b07834b07fb5eeb836005c23fcb3a6b6cc2683631a9d4b13c"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-save/hybrid-source-tui.json b/prototypes/connections/results/2026-09-24-native-save/hybrid-source-tui.json
new file mode 100644
index 0000000..2da02ec
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/hybrid-source-tui.json
@@ -0,0 +1,27 @@
+{
+ "profile": "native-source-document-terminal-editor",
+ "checks": [
+ "source parse and incompatible definitions fail before store creation",
+ "source CLI and TUI read the same document",
+ "changed source field layout drives TUI input encoding",
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1824,
+ "one_mib_peak_rss_kib": 3200,
+ "one_thousand_key_list_peak_rss_kib": 1936,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "portable": false,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "a3812efdf7d22cc98369eb878b91a1e5341d5bed18fd99b9fe4264177fd41973"
+}
diff --git a/prototypes/connections/results/2026-09-24-native-save/package-check.json b/prototypes/connections/results/2026-09-24-native-save/package-check.json
new file mode 100644
index 0000000..e57b8ca
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/package-check.json
@@ -0,0 +1,15 @@
+{
+ "archive_sha256": "b3c156eb7880ee4cb91b3fe52854cb5069ef035d082b7d539fa2a79592247ec5",
+ "archive_bytes": 57788,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-tui"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "selected storage keeps small values inline and maps large values",
+ "editing the packaged .pure source changes the executed reply",
+ "relocated source-loaded TUI and CLI share UTF-8, large and many-document paths"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-native-save/pure-document-fixed-cli-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-save/pure-document-fixed-cli-linux-aarch64.tar.gz
new file mode 100644
index 0000000..9f81ca0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/pure-document-fixed-cli-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-save/pure-document-fixed-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-save/pure-document-fixed-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..5114f58
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/pure-document-fixed-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-save/pure-document-flat-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-save/pure-document-flat-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..59abe7f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/pure-document-flat-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-save/pure-document-hybrid-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-native-save/pure-document-hybrid-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..313c49d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/pure-document-hybrid-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-save/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-native-save/pure-source-preview.tar.gz
new file mode 100644
index 0000000..9f29727
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-save/source-package-check.json b/prototypes/connections/results/2026-09-24-native-save/source-package-check.json
new file mode 100644
index 0000000..4c93ea8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-save/source-package-check.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "b258788cc9f90d8e6eccc964c8c9f4e2c5460df3dfbb9da07268da07799691e4",
+ "archive_bytes": 333925,
+ "source_files": 171,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean selected page store exports mixed revisions to the default flat store",
+ "clean one-MiB document fans out to two same-process Pure domains with independent conflict and release",
+ "clean selected page store runs the source-loaded TUI and relocatable CLI+TUI package",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-native-source/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-native-source/pure-source-preview.tar.gz
new file mode 100644
index 0000000..40d2e5e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-source/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-native-source/source-check-linux-aarch64.json b/prototypes/connections/results/2026-09-24-native-source/source-check-linux-aarch64.json
new file mode 100644
index 0000000..8fc4225
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-native-source/source-check-linux-aarch64.json
@@ -0,0 +1,13 @@
+{
+ "archive_sha256": "39a450a8a2e2cbfad39b95b9e91ede9899f2530cf9574ebff5d7b3748b9b0c3a",
+ "archive_bytes": 325436,
+ "source_files": 166,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-linux-aarch64.tar.gz
new file mode 100644
index 0000000..26c92da
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-linux-aarch64.tar.gz.check.json b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-linux-aarch64.tar.gz.check.json
new file mode 100644
index 0000000..b20331e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-linux-aarch64.tar.gz.check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "8a6dc8691eca1eb0a2b6daaccfd9e58c64777e5b42a4bb73c4b21b72375b880c",
+ "archive_bytes": 12886,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..f208ccf
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-tui-linux-aarch64.tar.gz.check.json b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-tui-linux-aarch64.tar.gz.check.json
new file mode 100644
index 0000000..2ca530a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-fixed-cli-tui-linux-aarch64.tar.gz.check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "5cb94eed37f7c7acbaad85d20715f2cc42d84d5d0de3af4788db284c9ede3e9e",
+ "archive_bytes": 31965,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-linux-aarch64.tar.gz
new file mode 100644
index 0000000..b026d9a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-linux-aarch64.tar.gz.check.json b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-linux-aarch64.tar.gz.check.json
new file mode 100644
index 0000000..fcc2a79
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-linux-aarch64.tar.gz.check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "d83048e6804252857ae80b6ee843fe8c9346802b9f1f9df30188845338e227af",
+ "archive_bytes": 22655,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..101a1fa
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-tui-linux-aarch64.tar.gz.check.json b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-tui-linux-aarch64.tar.gz.check.json
new file mode 100644
index 0000000..1f72434
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-document-source-cli-tui-linux-aarch64.tar.gz.check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "6f7a534dca12bb670cb4a4f6d28e3d9e569f0667015415c3c0473b5a0f909361",
+ "archive_bytes": 51005,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-tui"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "relocated source-loaded TUI and CLI share UTF-8, large and many-document paths"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-opaque-core/pure-source-preview.tar.gz
new file mode 100644
index 0000000..ce3e1b1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-opaque-core/source-package-check.json b/prototypes/connections/results/2026-09-24-opaque-core/source-package-check.json
new file mode 100644
index 0000000..898639f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-opaque-core/source-package-check.json
@@ -0,0 +1,15 @@
+{
+ "archive_sha256": "c0c3983f25088eb75ccf621cee264c210ea99d888f675e3bbb2ca2c59ea3246e",
+ "archive_bytes": 334682,
+ "source_files": 171,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean selected page store exports mixed revisions to the default flat store",
+ "clean one-MiB document fans out to two same-process Pure domains with independent conflict and release",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/app-asan.json b/prototypes/connections/results/2026-09-24-paged-storage/app-asan.json
new file mode 100644
index 0000000..121a548
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/app-asan.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11679,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 2,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 114,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "52e81f7277f11cddc8178a6be1f0693a39210445b7d338e3907c50c2f696f6b6",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "4e4bf4bd1f107510521703d49b207cad40b4d05e4d391fb997a34c1128cf2739",
+ "editor_sha256": "d2e3720a54597506cbe1262fdd6ef380a7bf3a7e7ef9012f4ae7dabf07fc781d",
+ "binary_sha256": "14e8472baf7c536c40dfbd1197b4e8be03099d1829e361456370ff678bb31cb6",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store-paged.c": "98ac90368b5be8fba5f9cd998145739d13c0003b822f048e4acbc517228e147e",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "58526592ee906833718101f1d33878d66c5e357097d5347d02755d922c36dda9",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "26c44763b13cbe80800ece1c6f1ab6c330d1d201edb9ea421e67cf24e8546fd2",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/app-release.json b/prototypes/connections/results/2026-09-24-paged-storage/app-release.json
new file mode 100644
index 0000000..bdaf2f7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/app-release.json
@@ -0,0 +1,635 @@
+{
+ "kind": "prepared-connection-correctness-not-performance",
+ "checks": [
+ "fragmented request and binary bytes round trip",
+ "conditional create and stale revision preserve committed bytes",
+ "writer contention and invalid extent fail without overwriting data",
+ "two native writers cannot both create the same expected revision",
+ "incomplete request never commits and releases its allocation",
+ "borrowed read remains the same snapshot during another commit",
+ "receiver reset aborts an outstanding borrowed transfer",
+ "unsupported framing and oversized payload are rejected before effects",
+ "existing workbench manipulation restores in a fresh runtime and reports conflict",
+ "invalid or non-idle restore preserves local state and does not adopt remote revision",
+ "revision above JavaScript safe integer round trips without numeric coercion",
+ "unread acknowledgment does not undo commit or permit a stale retry",
+ "empty body has a valid lifetime and stored revision",
+ "committed authoring state survives process restart",
+ "slow consumer retains its lease; budget rejects another; deadline releases it",
+ "connection slots stay bounded and recover after header deadlines",
+ "authored nested read maps only final demand while preserving parent bounds and revision",
+ "unused checked view still fails even when response range would be valid",
+ "authored write and reply share selected input; invalid parent prevents the storage effect",
+ "body-free response preserves read existence and malformed-object errors",
+ "input-backed response survives partial send and releases on finish or abort without undoing commit",
+ "invalid authored program fails preparation before creating storage or accepting requests",
+ "text client uses character selection; named numeric fields select and persist the matching UTF-8 bytes",
+ "truncated layouts and invalid data-dependent ranges never change storage; empty and end selections remain valid",
+ "changed declaration order and unaligned numeric fields determine access; aliases add no dynamic steps",
+ "unused dynamic field selection retains its validation before the write effect",
+ "named variable tail reads use the same file version and charge only the selected suffix",
+ "data-dependent response keeps and charges the original input through partial transmission",
+ "native authored byte edit and fresh native process restore UTF-8 content",
+ "native stale revision and invalid byte position preserve the committed document",
+ "native convenience editor derives unaligned reordered field positions from the authored program",
+ "raw native apply runs another authored input contract without changing the executor",
+ "native CLI and external HTTP share revisions and the same authored storage effect in both directions",
+ "partial or invalid edit input never modifies the stored document",
+ "two processes cannot both splice the same expected document revision",
+ "1 MiB document changes with 11 input credits; larger input is rejected before an effect"
+ ],
+ "prepared_connections": {
+ "excerpt": {
+ "read": {
+ "to_end": false,
+ "offset": 32,
+ "length": 16,
+ "minimum_source_bytes": 80
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 2,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "write": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 5,
+ "length": 4,
+ "minimum_source_bytes": 12
+ },
+ "reply_input": true,
+ "view_definitions": 3,
+ "range_definitions": 2,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "field_connections": {
+ "selection": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 8
+ },
+ "reply_input": true,
+ "view_definitions": 2,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 8,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 0,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 4,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "reordered": {
+ "read": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "write": {
+ "to_end": false,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "reply_input": true,
+ "view_definitions": 4,
+ "range_definitions": 1,
+ "runtime_view_steps": 1,
+ "write_step": 1,
+ "reply_step": 1,
+ "prepared_program_bytes": 680,
+ "steps": [
+ {
+ "source_step": 0,
+ "source": {
+ "offset": 11,
+ "length": 0,
+ "to_end": true
+ },
+ "offset": {
+ "value": 7,
+ "from_u32le": true
+ },
+ "length": {
+ "value": 3,
+ "from_u32le": true
+ }
+ }
+ ],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ },
+ "field_get": {
+ "read": {
+ "to_end": true,
+ "offset": 11,
+ "length": 0,
+ "minimum_source_bytes": 11
+ },
+ "write": {
+ "to_end": true,
+ "offset": 0,
+ "length": 0,
+ "minimum_source_bytes": 0
+ },
+ "reply_input": false,
+ "view_definitions": 1,
+ "range_definitions": 0,
+ "runtime_view_steps": 0,
+ "write_step": 0,
+ "reply_step": 0,
+ "prepared_program_bytes": 680,
+ "steps": [],
+ "write_effect": "write",
+ "splice_offset": {
+ "value": 0,
+ "from_u32le": false
+ },
+ "splice_remove": {
+ "value": 0,
+ "from_u32le": false
+ }
+ }
+ },
+ "document_edits": {
+ "large_document_bytes": 1048576,
+ "small_edit_input_bytes": 11,
+ "storage_rewrites_full_extent": true,
+ "storage_scratch_bytes": 4096,
+ "kind": "correctness-and-admission-not-total-memory-or-performance"
+ },
+ "server_runs": [
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 6,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 0,
+ "gets": 0,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 6,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048583,
+ "payload_budget": 4194304,
+ "peak_connections": 2,
+ "accepted": 42,
+ "commits": 12,
+ "gets": 15,
+ "conflicts": 4,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 32,
+ "ingress_prefix_copy_bytes": 11674,
+ "borrowed_output_bytes": 2115420,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 2553,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2556,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 12,
+ "commits": 0,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 9,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048582,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 80,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 2,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 16,
+ "payload_budget": 16,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 16,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 12,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 5,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 12,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 0,
+ "payload_budget": 1,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 0,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 0,
+ "budget_rejections": 2,
+ "expired": 0,
+ "releases": 5,
+ "ingress_prefix_copy_bytes": 8006,
+ "borrowed_output_bytes": 3145734,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 54,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 20,
+ "commits": 3,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 17,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 57,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 19,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 8,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 14,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 1,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 34,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 3,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 0,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 23,
+ "payload_budget": 23,
+ "peak_connections": 1,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 23,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 1048584,
+ "peak_connections": 2,
+ "accepted": 4,
+ "commits": 1,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 3,
+ "ingress_prefix_copy_bytes": 3998,
+ "borrowed_output_bytes": 2097091,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 9,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 1,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 29,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 10,
+ "commits": 1,
+ "gets": 4,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 10,
+ "ingress_prefix_copy_bytes": 7,
+ "borrowed_output_bytes": 113,
+ "server_structure_bytes": 41528
+ },
+ {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 11,
+ "payload_budget": 11,
+ "peak_connections": 1,
+ "accepted": 2,
+ "commits": 1,
+ "gets": 0,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 1,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 3,
+ "server_structure_bytes": 41528
+ }
+ ],
+ "storage": "immutable-byte-extents-v1",
+ "execution_core": {
+ "runtime_tests": "passed",
+ "domain_bytes": 200,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "forwarding_chain": 1024,
+ "native_storage_pipeline": true
+ },
+ "execution_core_test_sha256": "ecc89dcd0868ae701fa3d3ffbebae1f90447899d7802441a0062adc45e4f171f",
+ "document_edit_units": {
+ "splice_tests": "passed",
+ "checks": [
+ "authored-fields-and-atomic-parse-failure",
+ "binary-edit-oracle-and-old-snapshot",
+ "bounds-conflict-size-overflow",
+ "publication-failures-and-uncertain-durability",
+ "cancel-admission-and-borrowed-reply"
+ ]
+ },
+ "document_edit_test_sha256": "2d230f27ab5e3e6cd4d65d52015e456995aabc55b50ef665880755b9d01cca5d",
+ "editor_sha256": "497577bf9811b3ce787e27c6170a322ea553cdab2371b4f71eb51115a9045a16",
+ "binary_sha256": "b3df35ce2e25dc00578c79e47f6c5a21334da31df38cd482d9e71b835597f9cf",
+ "environment": {
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "machine": "aarch64",
+ "python": "3.14.7",
+ "node": "v24.20.0"
+ },
+ "source_sha256": {
+ "prototypes/connections/store-paged.c": "98ac90368b5be8fba5f9cd998145739d13c0003b822f048e4acbc517228e147e",
+ "prototypes/connections/flow.c": "3957de06e33985a8310954af07b33c2a1d02a4afdf9bd112d06c99c0b5df7749",
+ "prototypes/connections/flow.h": "289ff43d191270066e238235023f096946f3f561ec5825d2f6c26006db5fc421",
+ "prototypes/connections/store.h": "e3cf5f169be02e40f1274105046f29a63a46cd153beaf204d33d6100b9c869b8",
+ "prototypes/connections/program.c": "d7186634d2bfd83bbaf87ea3bafdec8d14be8f556cbf3d9877d07e0074b4b389",
+ "prototypes/connections/program.h": "b9ea0af3759150637ccba9362ccb73be374ed85b449b0461fc61fb14ee50e8bc",
+ "prototypes/connections/runtime.c": "a6c068c6a2cee214b3fe30241459394833917dfb6c0d33052460eab4c6a539a2",
+ "prototypes/connections/runtime.h": "ff03c0be92dcc482247a58a0be54d2dc5c270325b51ceeed37afc2ffa5480b1f",
+ "prototypes/connections/result.h": "00b6cf02262039fd90b197eb781f38c9771beaa8d65f394cba6d3f8d0b2ae79d",
+ "prototypes/connections/evaluate.c": "ee8b91efc733b9d305711b7cbb7b502ae5d3917e06f750b7f62b632ed0ea6d04",
+ "prototypes/connections/store-port.c": "d6bf17878b325e039360816edcbf8d68e41b373cf3e6128d7795e11ae21fdd6f",
+ "prototypes/connections/store-port.h": "a262bac93463bfe9939ca0bdc5989d1665aafc007d61e93c28ffc36478b1fde6",
+ "prototypes/connections/test-runtime.c": "58526592ee906833718101f1d33878d66c5e357097d5347d02755d922c36dda9",
+ "prototypes/connections/server.c": "76645bafe8e4e429155efe96c2d05a59aed506ba89736283e4fdae71a3d9a60f",
+ "prototypes/connections/check.py": "546ab85ba3495daa09a6299b23e05308718287b77bde326849ce9c26c8068eb2",
+ "prototypes/connections/check_edits.py": "7699eb4bda57ad860acf7be6da3e6de56d6b9a3dcf3b9ff9c7df104f5bcb9224",
+ "prototypes/connections/edit.c": "793d0bde277563c9e11f1225804fb1646e4ce495979d16e8d70d00322a7bec7b",
+ "prototypes/connections/test-splice.c": "2415188c89ff413f10d55a8cf1902e76c585cc4102f01d504bbf84dbe8d90a8f",
+ "prototypes/connections/test-flow.c": "2cd2618015ba6806b1a733af0fc7d0ed6aec48fdec117d18c3a8160f534e130b",
+ "prototypes/connections/test-program.c": "a1b65be05ab2e4e5ccbc56cd1e03e17b0d885f15dc027bf295371ec821e19cc8",
+ "prototypes/connections/test-fields.c": "e5856ae1985dc8407565ebf7b65702478a34a05081c955f127a10d3cdc900507",
+ "prototypes/connections/Makefile": "26c44763b13cbe80800ece1c6f1ab6c330d1d201edb9ea421e67cf24e8546fd2",
+ "prototypes/connections/core-layout.c": "e802b4976c53755ffc045ae9114ebdcf2989d526d8c871c3cfe89d057f4b82b0",
+ "prototypes/connections/check_core.py": "f80ead11764e870f0bde434c93233d518e5874fdb32f77444e7bd8bbe7398a10",
+ "prototypes/connections/core-budget.json": "b4eceaffce900144470dd29076164039b8729bad4ba849789d212e7c952f5082",
+ "prototypes/connections/examples/editor.pure": "8ca6c191b98bf53a592ce24f2b5cd040e41f05c4ccdda7a072d5d7f79870c06a",
+ "prototypes/connections/examples/storage.pure": "6f2fd3733f46b762836405f40a9720de0b865f92a8bcbf9388dda0532c903c74",
+ "prototypes/connections/examples/excerpt.pure": "7ca1b9a4b6a06c32b95e37bcdeb2202ef912ffbf16163f7eea2b00574c703c16",
+ "prototypes/connections/examples/selection.pure": "90a19a080dd31b532163b8063057beee4701d8f74163ac4083833a1d664fe986",
+ "prototypes/connections/examples/select-text.py": "3211ce21bf6058f0131544959272587af4edb3fd5a956aee0a940ab19888f944",
+ "prototypes/workbench/remote.mjs": "6f5aa2bc5a3c88749b2b688c5631eed9e4a5ab41d72eca168bfb67941a8cff2f",
+ "prototypes/workbench/cli.mjs": "55a5ead56fc8ad4c3f2391505fc3dbfa477ccff5b68fc208f700da24d5e194da",
+ "prototypes/workbench/web/core.wasm": "e5187c44f8d2df952a85e4cf8102b71dbec6c43420893b3544a6f8514a1bff5c",
+ "prototypes/workbench/web/runtime.mjs": "9cf12270bb39b3d6ce0384c56df8bdfabfd9459d3375cc7819290a5fe3e5db54",
+ "prototypes/workbench/web/compiler.mjs": "349139612d1f7da5f75ef21c65aa697963b760cb35321150fc36f67f3b40adf1",
+ "prototypes/workbench/web/project.mjs": "8af4cd1a60bbb217c896be20c7c6b8d33989f2166d06e736bf1479d8ecdc8b35",
+ "prototypes/workbench/examples/direct.pure": "57177e5197d75a6185cd3ac5df2be920ddba9a9b0fcc2dddab3560b815249f0a"
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/gtk-flow.json b/prototypes/connections/results/2026-09-24-paged-storage/gtk-flow.json
new file mode 100644
index 0000000..4a58c4b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/gtk-flow.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_window_rss_kib": 44656, "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/memory.json b/prototypes/connections/results/2026-09-24-paged-storage/memory.json
new file mode 100644
index 0000000..512da26
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/memory.json
@@ -0,0 +1,14 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-native-document-cli-memory",
+ "scope": "Peak process RSS via a small fork/wait4 helper on Linux AArch64. Covers this CLI, libc, program parsing, store, and one 1 MiB document workload; excludes filesystem cache, kernel buffers, other processes, selected TLS/GTK hosts, and other applications. These are regression ceilings for this toolchain, not a universal memory guarantee.",
+ "samples": {
+ "small_edit_rss_kib": 1104,
+ "one_mib_edit_rss_kib": 2128,
+ "one_mib_show_rss_kib": 1056
+ },
+ "budget_sha256": "53144cabe646e0478f25f4e770ce01bad06f4984ef47f5160d212c02c0b7569f",
+ "binary_sha256": "497577bf9811b3ce787e27c6170a322ea553cdab2371b4f71eb51115a9045a16",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41"
+}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/package-full.json b/prototypes/connections/results/2026-09-24-paged-storage/package-full.json
new file mode 100644
index 0000000..88f0795
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/package-full.json
@@ -0,0 +1,20 @@
+{
+ "archive_sha256": "08565ad139a5f9ad8ab52f96adde37dc092524e9bf699d9441787c489d8d11f1",
+ "archive_bytes": 111765,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-connections",
+ "pure-document-peer",
+ "pure-edit-window"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted HTTP host updates the same document as the native CLI",
+ "extracted C/Python TLS peers share a 1 MiB document and recover",
+ "extracted GTK window and selected external host edit the same document"
+ ],
+ "peer_idle_rss_kib": 7856,
+ "peer_after_large_work_rss_kib": 9552
+}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/package-micro.json b/prototypes/connections/results/2026-09-24-paged-storage/package-micro.json
new file mode 100644
index 0000000..552cea9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/package-micro.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "b247ba1a453c2500ec41e9161e130ec9a3b6c9316910fe655920d6fcfb62ec45",
+ "archive_bytes": 25456,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/paged-profile.json b/prototypes/connections/results/2026-09-24-paged-storage/paged-profile.json
new file mode 100644
index 0000000..d898c44
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/paged-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-paged-document-storage",
+ "scope": "Selected 16 KiB-page document storage backend on Linux AArch64/GCC 14. Same linked-code and direct-dependency ceilings as the flat backend; excludes libc, process RAM, filesystem cache and journal, and optional TLS/GTK. Any failure requires review, not automatic relaxation.",
+ "budget_sha256": "728cbe5488a86c7cb588a1b9e53d5ddc8aafe617c229624d7abe3e3a68f50699",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 39960,
+ "data": 1000,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "497577bf9811b3ce787e27c6170a322ea553cdab2371b4f71eb51115a9045a16"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 46824,
+ "data": 1088,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "b3df35ce2e25dc00578c79e47f6c5a21334da31df38cd482d9e71b835597f9cf"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/peer.json b/prototypes/connections/results/2026-09-24-paged-storage/peer.json
new file mode 100644
index 0000000..fa238e3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/peer.json
@@ -0,0 +1,16 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 7840,
+ "server_after_large_work_rss_kib": 9536
+}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/pure-document-paged-authoring-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-paged-storage/pure-document-paged-authoring-linux-aarch64.tar.gz
new file mode 100644
index 0000000..259dac1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/pure-document-paged-authoring-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/pure-document-paged-micro-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-paged-storage/pure-document-paged-micro-linux-aarch64.tar.gz
new file mode 100644
index 0000000..ed06d92
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/pure-document-paged-micro-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/unit-asan.json b/prototypes/connections/results/2026-09-24-paged-storage/unit-asan.json
new file mode 100644
index 0000000..697b69c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/unit-asan.json
@@ -0,0 +1 @@
+{"paged_storage":"snapshot-patch-range-compaction-crash-conflict-uncertain","mixed_edits":128}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/unit.json b/prototypes/connections/results/2026-09-24-paged-storage/unit.json
new file mode 100644
index 0000000..697b69c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/unit.json
@@ -0,0 +1 @@
+{"paged_storage":"snapshot-patch-range-compaction-crash-conflict-uncertain","mixed_edits":128}
diff --git a/prototypes/connections/results/2026-09-24-paged-storage/write-cost.json b/prototypes/connections/results/2026-09-24-paged-storage/write-cost.json
new file mode 100644
index 0000000..f3197a8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-paged-storage/write-cost.json
@@ -0,0 +1,49 @@
+{
+ "profile": "linux-aarch64-16k-page-document-replacement",
+ "workloads": [
+ "replace last byte of 1 MiB document",
+ "replace one-byte document"
+ ],
+ "unit": "successful user-space write syscall bytes targeting object files",
+ "excludes": "physical device writes, filesystem journal, metadata and directory sync cost",
+ "one_mib": {
+ "flat": {
+ "object_write_syscall_bytes": 1048600,
+ "object_write_calls": 258,
+ "object_files": {
+ "obj-large": 1048600
+ },
+ "binary_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03"
+ },
+ "paged": {
+ "object_write_syscall_bytes": 16944,
+ "object_write_calls": 3,
+ "object_files": {
+ "obj-large": 560,
+ "dat-large-0000000000000001": 1064960
+ },
+ "binary_sha256": "497577bf9811b3ce787e27c6170a322ea553cdab2371b4f71eb51115a9045a16"
+ },
+ "flat_to_paged_ratio": 61.8862134088763
+ },
+ "one_byte": {
+ "flat": {
+ "object_write_syscall_bytes": 25,
+ "object_write_calls": 2,
+ "object_files": {
+ "obj-tiny": 25
+ },
+ "binary_sha256": "b5c6ec82a1e9c8a1391d1c4ac680e7f33e53dafe5c29ac8a956d5097653b1a03"
+ },
+ "paged": {
+ "object_write_syscall_bytes": 16440,
+ "object_write_calls": 3,
+ "object_files": {
+ "obj-tiny": 56,
+ "dat-tiny-0000000000000001": 32768
+ },
+ "binary_sha256": "497577bf9811b3ce787e27c6170a322ea553cdab2371b4f71eb51115a9045a16"
+ },
+ "paged_to_flat_ratio": 657.6
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-peer-source/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-portable-peer-source/pure-source-preview.tar.gz
new file mode 100644
index 0000000..ac8ed09
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-peer-source/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-portable-peer-source/source-check-linux-aarch64.json b/prototypes/connections/results/2026-09-24-portable-peer-source/source-check-linux-aarch64.json
new file mode 100644
index 0000000..0b54aff
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-peer-source/source-check-linux-aarch64.json
@@ -0,0 +1,15 @@
+{
+ "archive_sha256": "bf51f79c400f820b48dbf78522449cda6625563ce860809e86d76a8023377dbb",
+ "archive_bytes": 321958,
+ "source_files": 165,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17 build and host-neutral behavior tests pass",
+ "clean fixed and source-loaded native terminal PTY scenarios pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean native TLS client and both server profiles pass authenticated document work",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-peer/client-server-linux-aarch64.json b/prototypes/connections/results/2026-09-24-portable-peer/client-server-linux-aarch64.json
new file mode 100644
index 0000000..b967ae6
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-peer/client-server-linux-aarch64.json
@@ -0,0 +1,17 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": null,
+ "server_after_large_work_rss_kib": null,
+ "portable": true
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-peer/client-server-linux-rss-regression.json b/prototypes/connections/results/2026-09-24-portable-peer/client-server-linux-rss-regression.json
new file mode 100644
index 0000000..635361a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-peer/client-server-linux-rss-regression.json
@@ -0,0 +1,17 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 7968,
+ "server_after_large_work_rss_kib": 9712,
+ "portable": false
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-peer/client-server-profile.json b/prototypes/connections/results/2026-09-24-portable-peer/client-server-profile.json
new file mode 100644
index 0000000..f8e8511
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-peer/client-server-profile.json
@@ -0,0 +1,23 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-document-peer",
+ "scope": "Review threshold for the explicitly selected authenticated document host on Linux AArch64/GCC 14. Includes linked application code but excludes the shared OpenSSL/libc implementations, process heap, stack, mappings and kernel buffers. Check measured whole-process RSS separately.",
+ "budget_sha256": "defe8efb4d544cdbf615de4d43d4ceba78fc7f1d958f245731202625052eb2ff",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-document-peer": {
+ "sections": {
+ "text": 46934,
+ "data": 1384,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6",
+ "libcrypto.so.3",
+ "libssl.so.3"
+ ],
+ "sha256": "06fc08105cb9833599b9c778797cf2be4ba8a6c1db514c836bb76667a8c7265e"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-peer/server-only-linux-aarch64.json b/prototypes/connections/results/2026-09-24-portable-peer/server-only-linux-aarch64.json
new file mode 100644
index 0000000..b967ae6
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-peer/server-only-linux-aarch64.json
@@ -0,0 +1,17 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": null,
+ "server_after_large_work_rss_kib": null,
+ "portable": true
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-peer/server-only-linux-rss-regression.json b/prototypes/connections/results/2026-09-24-portable-peer/server-only-linux-rss-regression.json
new file mode 100644
index 0000000..635361a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-peer/server-only-linux-rss-regression.json
@@ -0,0 +1,17 @@
+{
+ "profile": "selected-authenticated-document-peer",
+ "checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "server_idle_rss_kib": 7968,
+ "server_after_large_work_rss_kib": 9712,
+ "portable": false
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-peer/server-only-profile.json b/prototypes/connections/results/2026-09-24-portable-peer/server-only-profile.json
new file mode 100644
index 0000000..0f6a3ce
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-peer/server-only-profile.json
@@ -0,0 +1,23 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-selected-document-server",
+ "scope": "Reviewed server-only TLS peer ceiling on Linux AArch64/GCC 14. Excludes linked native client code and shared OpenSSL/libc implementations; process RSS is measured separately.",
+ "budget_sha256": "deae8827323061543193779ada90d1bca4db3a6dda80293e4ad28a9526be9819",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-document-server": {
+ "sections": {
+ "text": 43462,
+ "data": 1352,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6",
+ "libcrypto.so.3",
+ "libssl.so.3"
+ ],
+ "sha256": "728025cfbdbcdb6d212a2ec8297a0740967653c77ae8908d923c59ddd4ea0315"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-source/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-portable-source/pure-source-preview.tar.gz
new file mode 100644
index 0000000..8ef47db
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-source/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-portable-source/source-check-linux-aarch64.json b/prototypes/connections/results/2026-09-24-portable-source/source-check-linux-aarch64.json
new file mode 100644
index 0000000..57a1027
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-source/source-check-linux-aarch64.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "5f1766fefe2c319d86c3ff57c881638a9d1ee24374dea33c614e25577d087814",
+ "archive_bytes": 321399,
+ "source_files": 165,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17 build and host-neutral behavior tests pass",
+ "clean fixed and source-loaded native terminal PTY scenarios pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-tui/fixed-linux-aarch64.json b/prototypes/connections/results/2026-09-24-portable-tui/fixed-linux-aarch64.json
new file mode 100644
index 0000000..3e0fe7d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-tui/fixed-linux-aarch64.json
@@ -0,0 +1,24 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": null,
+ "one_mib_peak_rss_kib": null,
+ "one_thousand_key_list_peak_rss_kib": null,
+ "one_mib_peak_rss_limit_kib": 0,
+ "portable": true,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "45491c3e28193024d6eb77cbd6569ee8b7470d11ec4126ff4515dba116790308"
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-tui/fixed-linux-rss-regression.json b/prototypes/connections/results/2026-09-24-portable-tui/fixed-linux-rss-regression.json
new file mode 100644
index 0000000..19090b0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-tui/fixed-linux-rss-regression.json
@@ -0,0 +1,24 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1776,
+ "one_mib_peak_rss_kib": 3168,
+ "one_thousand_key_list_peak_rss_kib": 1888,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "portable": false,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "45491c3e28193024d6eb77cbd6569ee8b7470d11ec4126ff4515dba116790308"
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-tui/source-linux-aarch64.json b/prototypes/connections/results/2026-09-24-portable-tui/source-linux-aarch64.json
new file mode 100644
index 0000000..53b3218
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-tui/source-linux-aarch64.json
@@ -0,0 +1,27 @@
+{
+ "profile": "native-source-document-terminal-editor",
+ "checks": [
+ "source parse and incompatible definitions fail before store creation",
+ "source CLI and TUI read the same document",
+ "changed source field layout drives TUI input encoding",
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": null,
+ "one_mib_peak_rss_kib": null,
+ "one_thousand_key_list_peak_rss_kib": null,
+ "one_mib_peak_rss_limit_kib": 0,
+ "portable": true,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "e4fb890935f77a7b359163758ce4c44f3710d1a99130a7d883a4f7329a20a70d"
+}
diff --git a/prototypes/connections/results/2026-09-24-portable-tui/source-linux-rss-regression.json b/prototypes/connections/results/2026-09-24-portable-tui/source-linux-rss-regression.json
new file mode 100644
index 0000000..b112863
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-portable-tui/source-linux-rss-regression.json
@@ -0,0 +1,27 @@
+{
+ "profile": "native-source-document-terminal-editor",
+ "checks": [
+ "source parse and incompatible definitions fail before store creation",
+ "source CLI and TUI read the same document",
+ "changed source field layout drives TUI input encoding",
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1856,
+ "one_mib_peak_rss_kib": 3664,
+ "one_thousand_key_list_peak_rss_kib": 1936,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "portable": false,
+ "terminal_locale": "C.UTF-8",
+ "binary_sha256": "e4fb890935f77a7b359163758ce4c44f3710d1a99130a7d883a4f7329a20a70d"
+}
diff --git a/prototypes/connections/results/2026-09-24-posix-idle/fixed-profile.json b/prototypes/connections/results/2026-09-24-posix-idle/fixed-profile.json
new file mode 100644
index 0000000..b56deb9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-posix-idle/fixed-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files.",
+ "budget_sha256": "2b7e550992abb1872e52846dec712fab59b78692b776fd7e648d7976299f4b2a",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19244,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8"
+ },
+ "pure-connections-fixed": {
+ "sections": {
+ "text": 26261,
+ "data": 1028,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "1999ad534e9091fbaca096402ba2fbeaeb92c9fb4d4150cacaf309e9a9cd9555"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-posix-idle/fixed-server-regression.json b/prototypes/connections/results/2026-09-24-posix-idle/fixed-server-regression.json
new file mode 100644
index 0000000..d96f70c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-posix-idle/fixed-server-regression.json
@@ -0,0 +1,68 @@
+{
+ "profile": "build-time-prepared-http-document-host",
+ "fixed_source_cli_same_document": "pass",
+ "conditional_conflict_and_invalid_splice": "pass",
+ "one_mib_roundtrip_and_native_edit": "pass",
+ "slow_consumer_budget_and_release": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 7,
+ "ingress_prefix_copy_bytes": 11,
+ "borrowed_output_bytes": 2097177,
+ "server_structure_bytes": 40848
+ },
+ "source_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 6,
+ "commits": 1,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 6,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097162,
+ "server_structure_bytes": 41528
+ },
+ "limited_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048586,
+ "server_structure_bytes": 40848
+ },
+ "fixed_idle_rss_kib": 1520,
+ "source_idle_rss_kib": 1552,
+ "fixed_after_large_rss_kib": 1648,
+ "source_after_large_rss_kib": 1680,
+ "fixed_peak_rss_kib": 2144,
+ "source_peak_rss_kib": 1680,
+ "fixed_peak_rss_limit_kib": 4096,
+ "fixed_sha256": "1999ad534e9091fbaca096402ba2fbeaeb92c9fb4d4150cacaf309e9a9cd9555",
+ "source_sha256": "1d4e858f18e7cea6df263e2d716898ba7a15b966ecda7e1145b21b80f8fe8f88"
+}
diff --git a/prototypes/connections/results/2026-09-24-posix-idle/package.json b/prototypes/connections/results/2026-09-24-posix-idle/package.json
new file mode 100644
index 0000000..5085bdd
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-posix-idle/package.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "47f8a4943187edc3733f5900790d5c240d25e2042a0b6c3567eb5da2ece68dd1",
+ "archive_bytes": 32346,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-posix-idle/pure-document-fixed-http-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-posix-idle/pure-document-fixed-http-linux-aarch64.tar.gz
new file mode 100644
index 0000000..8b50236
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-posix-idle/pure-document-fixed-http-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-posix-idle/reproducible-comparison.json b/prototypes/connections/results/2026-09-24-posix-idle/reproducible-comparison.json
new file mode 100644
index 0000000..7548186
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-posix-idle/reproducible-comparison.json
@@ -0,0 +1,21 @@
+{
+ "profile": "idle-http-host-poll-syscalls",
+ "observation_seconds": 1.25,
+ "before": {
+ "poll_calls": 25,
+ "timeout_values_ms": [
+ 50
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=PO",
+ "binary_sha256": "7dd0010fa6d6024afa2fe35d57a4c73f33ac632e732616ac8f8853d7b22d79b3"
+ },
+ "after": {
+ "poll_calls": 1,
+ "timeout_values_ms": [
+ -1
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 10, NULL, NULL, 0) = ? ERESTARTNOHAND (To be restarted if no handler)\n--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=941369, si_uid=1000} ---\n",
+ "binary_sha256": "1999ad534e9091fbaca096402ba2fbeaeb92c9fb4d4150cacaf309e9a9cd9555"
+ },
+ "deadline_driven_idle_wait": "pass"
+}
diff --git a/prototypes/connections/results/2026-09-24-posix-idle/service-scale.json b/prototypes/connections/results/2026-09-24-posix-idle/service-scale.json
new file mode 100644
index 0000000..c1396ab
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-posix-idle/service-scale.json
@@ -0,0 +1,62 @@
+{
+ "profile": "document-app-many-objects-concurrent-clients",
+ "documents_per_variant": 1024,
+ "clients": 8,
+ "body_bytes": 8192,
+ "operations_per_variant": 4096,
+ "server_budget_bytes": 1048576,
+ "peak_rss_limit_kib": 4096,
+ "same_final_documents": "pass",
+ "fixed": {
+ "binary_sha256": "1999ad534e9091fbaca096402ba2fbeaeb92c9fb4d4150cacaf309e9a9cd9555",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1504,
+ "peak_rss_kib": 1680,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49185,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 326623,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 40848
+ }
+ },
+ "source": {
+ "binary_sha256": "1d4e858f18e7cea6df263e2d716898ba7a15b966ecda7e1145b21b80f8fe8f88",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1552,
+ "peak_rss_kib": 1712,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49168,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 366236,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 41528
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-posix-idle/source-profile.json b/prototypes/connections/results/2026-09-24-posix-idle/source-profile.json
new file mode 100644
index 0000000..d5795da
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-posix-idle/source-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35807,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "bce466328ac730ccb7cd22c7a0c4e2960bc94a0f20ac9f036e232bd499521ff7"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 43778,
+ "data": 1068,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "1d4e858f18e7cea6df263e2d716898ba7a15b966ecda7e1145b21b80f8fe8f88"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-prefix-find/cli-tui.tar.gz b/prototypes/connections/results/2026-09-24-prefix-find/cli-tui.tar.gz
new file mode 100644
index 0000000..dff004b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-prefix-find/cli-tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-prefix-find/package-check.json b/prototypes/connections/results/2026-09-24-prefix-find/package-check.json
new file mode 100644
index 0000000..440bc20
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-prefix-find/package-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "54a579102d6f9563ee8d077e49eaf156ad3fc826e42532607fce45a75283b10d",
+ "archive_bytes": 32233,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-prefix-find/tui-profile.json b/prototypes/connections/results/2026-09-24-prefix-find/tui-profile.json
new file mode 100644
index 0000000..fd11cb1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-prefix-find/tui-profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app, including the bounded document browser. The raised text ceiling reviews its measured 2,541-byte addition; default CLI and core ceilings are unchanged. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS, including 1,024-key browsing, is checked by check_tui.py on the recorded Linux AArch64 host.",
+ "budget_sha256": "4d3097c9ec3c0139cbdd82161a74d610c15d31c6ee5625101410627664f925e7",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "sections": {
+ "text": 32175,
+ "data": 1036,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "39b5bcf605739eabd731e471a3f54e03592e2bfc0a405db5faacdb4df84d0b22"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-prefix-find/tui.json b/prototypes/connections/results/2026-09-24-prefix-find/tui.json
new file mode 100644
index 0000000..6588e17
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-prefix-find/tui.json
@@ -0,0 +1,22 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1824,
+ "one_mib_peak_rss_kib": 3200,
+ "one_thousand_key_list_peak_rss_kib": 1904,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "39b5bcf605739eabd731e471a3f54e03592e2bfc0a405db5faacdb4df84d0b22"
+}
diff --git a/prototypes/connections/results/2026-09-24-release-callback/async-core.json b/prototypes/connections/results/2026-09-24-release-callback/async-core.json
new file mode 100644
index 0000000..6e5371e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-release-callback/async-core.json
@@ -0,0 +1,55 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "selected-owner-thread-async-effects",
+ "max_text_bytes": 8192,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "effect_bytes": 128
+ },
+ "archive_members": [
+ "runtime-async.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Selected compact owner-thread completion extension without opt-in PURE_RUNTIME_METRICS. Host I/O and worker stacks are excluded. The default execution core and fixed document packages do not link this profile."
+ },
+ "layout": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8,
+ "effect_bytes": 128
+ },
+ "sections": {
+ "text": 7372,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime-async.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 6452\t 0\t 0\t 6452\t 1934\truntime-async.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution-async.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution-async.a)\n",
+ "archive_sha256": "e6b90a42ca7dc894483c920d59c606895a83d16fe2e6b4f1d0a6d36a83d7efb5",
+ "layout_binary_sha256": "be9307acf8264bc1b333dc05fa0e4b162f912ce8e8b82e3d20eddf49e269d42c",
+ "budget_sha256": "33afabc20949bc322af9e86b946d39147cd714e32d4e095bc0cc404d11aa79ad",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-release-callback/core.json b/prototypes/connections/results/2026-09-24-release-callback/core.json
new file mode 100644
index 0000000..6182c51
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-release-callback/core.json
@@ -0,0 +1,53 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Compact release object sections and C bookkeeping, without opt-in PURE_RUNTIME_METRICS, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 5980,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 5060\t 0\t 0\t 5060\t 13c4\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "c5f05b1fb9d51f244687425a1b1d2f8922f6f899f0b617b4de490c730d106e97",
+ "layout_binary_sha256": "04c008fb7e0b1ecc8435bce6fbc4478de6180a54da6538d8742acb9b51992fe3",
+ "budget_sha256": "e418419db6231305342ea8780149948e0e41e28b3afb937268e80b4695d3d5cd",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-release-callback/micro-package-check.json b/prototypes/connections/results/2026-09-24-release-callback/micro-package-check.json
new file mode 100644
index 0000000..9db433b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-release-callback/micro-package-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "722d68e58d948810c4a181d0dc832ad97bc5c65b5f5629d1af5866aff920e0b5",
+ "archive_bytes": 22758,
+ "selected_hosts": [
+ "pure-edit"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-release-callback/pure-document-micro-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-release-callback/pure-document-micro-linux-aarch64.tar.gz
new file mode 100644
index 0000000..44f9c7f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-release-callback/pure-document-micro-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-release-callback/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-release-callback/pure-source-preview.tar.gz
new file mode 100644
index 0000000..68e4f0a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-release-callback/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-release-callback/runtime.json b/prototypes/connections/results/2026-09-24-release-callback/runtime.json
new file mode 100644
index 0000000..6f6527d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-release-callback/runtime.json
@@ -0,0 +1 @@
+{"runtime_tests":"passed","domain_bytes":200,"work_slot_bytes":224,"ticket_bytes":24,"prepared_program_bytes":680,"forwarding_chain":1024,"native_storage_pipeline":true,"idle_slot_binding":true,"release_reentrancy_guard":true}
diff --git a/prototypes/connections/results/2026-09-24-release-callback/source-package-check.json b/prototypes/connections/results/2026-09-24-release-callback/source-package-check.json
new file mode 100644
index 0000000..459429c
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-release-callback/source-package-check.json
@@ -0,0 +1,15 @@
+{
+ "archive_sha256": "cff657597c0cc33bd9185c8460e0d84f0843da20a786578324ac612fa255c2b4",
+ "archive_bytes": 333037,
+ "source_files": 170,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean selected page store exports mixed revisions to the default flat store",
+ "clean one-MiB document fans out to two same-process Pure domains with independent conflict and release",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-server-only-package/combined-peer-package-check.json b/prototypes/connections/results/2026-09-24-server-only-package/combined-peer-package-check.json
new file mode 100644
index 0000000..d8ed889
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-server-only-package/combined-peer-package-check.json
@@ -0,0 +1,27 @@
+{
+ "archive_sha256": "d1592ec4e4085ebe328c01ccf49911c383fc87908344cfea5fb9bca56a0fef96",
+ "archive_bytes": 49382,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-document-peer"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted C/Python TLS peers share a 1 MiB document and recover"
+ ],
+ "peer_checks": [
+ "mutual certificate identity, server hostname and ALPN separation",
+ "program source identity checked before C client sends work",
+ "persistent external TLS client: create, read, conflict and recovery",
+ "native peer edit and local CLI use the same authored document and storage",
+ "fragmented 1 MiB direct ingress, demand-selected reply and one-byte splice",
+ "native C peer uploads 1 MiB and receives only the requested metadata",
+ "incomplete, invalid and oversized frames do not publish a change",
+ "idle authenticated session closes after deadline",
+ "server restart and native C peer preserve the committed large document"
+ ],
+ "peer_idle_rss_kib": 7968,
+ "peer_after_large_work_rss_kib": 9712
+}
diff --git a/prototypes/connections/results/2026-09-24-server-only-package/pure-document-combined-peer-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-server-only-package/pure-document-combined-peer-linux-aarch64.tar.gz
new file mode 100644
index 0000000..ebd24da
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-server-only-package/pure-document-combined-peer-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-server-only-package/pure-document-server-only-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-server-only-package/pure-document-server-only-linux-aarch64.tar.gz
new file mode 100644
index 0000000..2a47d7e
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-server-only-package/pure-document-server-only-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-server-only-package/server-only-package-check.json b/prototypes/connections/results/2026-09-24-server-only-package/server-only-package-check.json
new file mode 100644
index 0000000..997287d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-server-only-package/server-only-package-check.json
@@ -0,0 +1,23 @@
+{
+ "archive_sha256": "34fb507c160e4aa719cf44fb4f8bbcb422d2c0ee6dc3f206f6a5fe3bc4d089b6",
+ "archive_bytes": 47686,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-document-server"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "extracted server-only TLS peer and external client share a 1 MiB document and recover"
+ ],
+ "peer_checks": [
+ "relocated server rejects invalid client identity, ALPN and hostname",
+ "external client and extracted CLI share a conditional document",
+ "fragmented one MiB ingress, selected reply and CLI-visible splice",
+ "truncated and invalid frames do not publish a change",
+ "relocated server restart restores the committed one MiB document"
+ ],
+ "peer_idle_rss_kib": 7968,
+ "peer_after_large_work_rss_kib": 8672
+}
diff --git a/prototypes/connections/results/2026-09-24-signal-safe-idle/fixed-profile.json b/prototypes/connections/results/2026-09-24-signal-safe-idle/fixed-profile.json
new file mode 100644
index 0000000..733fa60
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-signal-safe-idle/fixed-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-runner",
+ "scope": "Release-linked CLI and HTTP document hosts with one build-time prepared app. The source parser and compiler are separate build tools. These text ceilings apply only to the recorded Linux AArch64/GCC 14 toolchain and exclude libc, heap, stack, and storage files.",
+ "budget_sha256": "2b7e550992abb1872e52846dec712fab59b78692b776fd7e648d7976299f4b2a",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-fixed": {
+ "sections": {
+ "text": 19244,
+ "data": 920,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8"
+ },
+ "pure-connections-fixed": {
+ "sections": {
+ "text": 25790,
+ "data": 1024,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "fd474f7331ac47d22360f2bfe8ba491ff8ffac448107b41da74a00142ae97958"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-signal-safe-idle/fixed-server-regression.json b/prototypes/connections/results/2026-09-24-signal-safe-idle/fixed-server-regression.json
new file mode 100644
index 0000000..7857bde
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-signal-safe-idle/fixed-server-regression.json
@@ -0,0 +1,68 @@
+{
+ "profile": "build-time-prepared-http-document-host",
+ "fixed_source_cli_same_document": "pass",
+ "conditional_conflict_and_invalid_splice": "pass",
+ "one_mib_roundtrip_and_native_edit": "pass",
+ "slow_consumer_budget_and_release": "pass",
+ "runtime_parser_symbols_absent": "pass",
+ "fixed_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048584,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 7,
+ "commits": 2,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 7,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097177,
+ "server_structure_bytes": 40848
+ },
+ "source_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 4194304,
+ "peak_connections": 1,
+ "accepted": 6,
+ "commits": 1,
+ "gets": 3,
+ "conflicts": 1,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 6,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 2097162,
+ "server_structure_bytes": 41528
+ },
+ "limited_stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 1048576,
+ "payload_budget": 1048576,
+ "peak_connections": 2,
+ "accepted": 3,
+ "commits": 0,
+ "gets": 2,
+ "conflicts": 0,
+ "budget_rejections": 1,
+ "expired": 0,
+ "releases": 2,
+ "ingress_prefix_copy_bytes": 0,
+ "borrowed_output_bytes": 1048586,
+ "server_structure_bytes": 40848
+ },
+ "fixed_idle_rss_kib": 1504,
+ "source_idle_rss_kib": 1552,
+ "fixed_after_large_rss_kib": 1632,
+ "source_after_large_rss_kib": 1680,
+ "fixed_peak_rss_kib": 2112,
+ "source_peak_rss_kib": 2096,
+ "fixed_peak_rss_limit_kib": 4096,
+ "fixed_sha256": "fd474f7331ac47d22360f2bfe8ba491ff8ffac448107b41da74a00142ae97958",
+ "source_sha256": "9818530bdadd3da2c3cd63feb24f0585f8527887bcc9c8528d67736ee3a97653"
+}
diff --git a/prototypes/connections/results/2026-09-24-signal-safe-idle/package.json b/prototypes/connections/results/2026-09-24-signal-safe-idle/package.json
new file mode 100644
index 0000000..8304c17
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-signal-safe-idle/package.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "413f88a31272c5a0851ab598673de5523fa12d913e0a077441aa342b506498e2",
+ "archive_bytes": 32023,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-signal-safe-idle/pure-document-fixed-http-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-signal-safe-idle/pure-document-fixed-http-linux-aarch64.tar.gz
new file mode 100644
index 0000000..54c21a2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-signal-safe-idle/pure-document-fixed-http-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-signal-safe-idle/reproducible-comparison.json b/prototypes/connections/results/2026-09-24-signal-safe-idle/reproducible-comparison.json
new file mode 100644
index 0000000..79f8c49
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-signal-safe-idle/reproducible-comparison.json
@@ -0,0 +1,21 @@
+{
+ "profile": "idle-http-host-poll-syscalls",
+ "observation_seconds": 1.25,
+ "before": {
+ "poll_calls": 25,
+ "timeout_values_ms": [
+ 50
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, {tv_sec=0, tv_nsec=50000000}, NULL, 0) = 0 (Timeout)\nppoll([{fd=3, events=PO",
+ "binary_sha256": "7dd0010fa6d6024afa2fe35d57a4c73f33ac632e732616ac8f8853d7b22d79b3"
+ },
+ "after": {
+ "poll_calls": 1,
+ "timeout_values_ms": [
+ -1
+ ],
+ "trace_excerpt": "ppoll([{fd=3, events=POLLIN}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}, {fd=-1}], 9, NULL, [], 8) = ? ERESTARTNOHAND (To be restarted if no handler)\n--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=932958, si_uid=1000} ---\n",
+ "binary_sha256": "fd474f7331ac47d22360f2bfe8ba491ff8ffac448107b41da74a00142ae97958"
+ },
+ "deadline_driven_idle_wait": "pass"
+}
diff --git a/prototypes/connections/results/2026-09-24-signal-safe-idle/service-scale-restored.json b/prototypes/connections/results/2026-09-24-signal-safe-idle/service-scale-restored.json
new file mode 100644
index 0000000..a4a9764
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-signal-safe-idle/service-scale-restored.json
@@ -0,0 +1,62 @@
+{
+ "profile": "document-app-many-objects-concurrent-clients",
+ "documents_per_variant": 1024,
+ "clients": 8,
+ "body_bytes": 8192,
+ "operations_per_variant": 4096,
+ "server_budget_bytes": 1048576,
+ "peak_rss_limit_kib": 4096,
+ "same_final_documents": "pass",
+ "fixed": {
+ "binary_sha256": "fd474f7331ac47d22360f2bfe8ba491ff8ffac448107b41da74a00142ae97958",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1520,
+ "peak_rss_kib": 1696,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49200,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 696751,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 40848
+ }
+ },
+ "source": {
+ "binary_sha256": "9818530bdadd3da2c3cd63feb24f0585f8527887bcc9c8528d67736ee3a97653",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "fresh_cli_restore_samples": 4,
+ "idle_rss_kib": 1552,
+ "peak_rss_kib": 1712,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 40993,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 410074,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 41528
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-signal-safe-idle/service-scale.json b/prototypes/connections/results/2026-09-24-signal-safe-idle/service-scale.json
new file mode 100644
index 0000000..4bedc63
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-signal-safe-idle/service-scale.json
@@ -0,0 +1,60 @@
+{
+ "profile": "document-app-many-objects-concurrent-clients",
+ "documents_per_variant": 1024,
+ "clients": 8,
+ "body_bytes": 8192,
+ "operations_per_variant": 4096,
+ "server_budget_bytes": 1048576,
+ "peak_rss_limit_kib": 4096,
+ "same_final_documents": "pass",
+ "fixed": {
+ "binary_sha256": "fd474f7331ac47d22360f2bfe8ba491ff8ffac448107b41da74a00142ae97958",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "idle_rss_kib": 1520,
+ "peak_rss_kib": 1712,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 49201,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 899986,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 40848
+ }
+ },
+ "source": {
+ "binary_sha256": "9818530bdadd3da2c3cd63feb24f0585f8527887bcc9c8528d67736ee3a97653",
+ "document_digest": "e54baed00186fb020edbbcd407d86471c136287de346e3386ce52d16883e488b",
+ "stored_objects": 1024,
+ "stored_file_bytes": 8413184,
+ "idle_rss_kib": 1552,
+ "peak_rss_kib": 1728,
+ "stats": {
+ "active": 0,
+ "retained_payload_bytes": 0,
+ "peak_retained_payload_bytes": 41010,
+ "payload_budget": 1048576,
+ "peak_connections": 8,
+ "accepted": 4096,
+ "commits": 2048,
+ "gets": 2048,
+ "conflicts": 0,
+ "budget_rejections": 0,
+ "expired": 0,
+ "releases": 4096,
+ "ingress_prefix_copy_bytes": 939752,
+ "borrowed_output_bytes": 25166848,
+ "server_structure_bytes": 41528
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-signal-safe-idle/source-profile.json b/prototypes/connections/results/2026-09-24-signal-safe-idle/source-profile.json
new file mode 100644
index 0000000..5bc9266
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-signal-safe-idle/source-profile.json
@@ -0,0 +1,32 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-default-document-hosts",
+ "scope": "Review thresholds for release-built default CLI and HTTP adapter on the recorded Linux AArch64/GCC 14 toolchain. These section sizes exclude shared libc, heap, stack, mapped files, kernel buffers, and optional GTK/TLS hosts. Any failure requires a cost review, not automatic relaxation.",
+ "budget_sha256": "8b1eb0dd4844757705c24a0674142e76d9ee83fdce80a841e87a08e757f1183d",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit": {
+ "sections": {
+ "text": 35807,
+ "data": 944,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "bce466328ac730ccb7cd22c7a0c4e2960bc94a0f20ac9f036e232bd499521ff7"
+ },
+ "pure-connections": {
+ "sections": {
+ "text": 43451,
+ "data": 1064,
+ "bss": 16
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "9818530bdadd3da2c3cd63feb24f0585f8527887bcc9c8528d67736ee3a97653"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-source-preview/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-source-preview/pure-source-preview.tar.gz
new file mode 100644
index 0000000..45e83a0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-preview/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-source-preview/source-check.json b/prototypes/connections/results/2026-09-24-source-preview/source-check.json
new file mode 100644
index 0000000..a3b7681
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-preview/source-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "a11a058fa0ba71878a0fed0ee63100566f580721fa5cb602ad25cd46e6b94f6f",
+ "archive_bytes": 316748,
+ "source_files": 161,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17 build and host-neutral behavior tests pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean Linux release behavior, code, dependency and RSS gates pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-source-tui/core.json b/prototypes/connections/results/2026-09-24-source-tui/core.json
new file mode 100644
index 0000000..63eb227
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/core.json
@@ -0,0 +1,53 @@
+{
+ "passed": true,
+ "failures": [],
+ "budget": {
+ "profile": "current-storage-execution-core",
+ "max_text_bytes": 6144,
+ "max_data_bytes": 0,
+ "max_bss_bytes": 0,
+ "layout_max_bytes": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680
+ },
+ "archive_members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols_allowed": [
+ "memcpy",
+ "memmove",
+ "memset",
+ "strlen"
+ ],
+ "scope": "Compact release object sections and C bookkeeping, without opt-in PURE_RUNTIME_METRICS, validated with GNU tools on Linux AArch64. Not total RAM, process RSS, stack, linked libraries, parser, storage, network or UI. 6 KiB is a regression ceiling for this profile, not a universal runtime size promise."
+ },
+ "layout": {
+ "domain_bytes": 128,
+ "work_slot_bytes": 224,
+ "ticket_bytes": 24,
+ "prepared_program_bytes": 680,
+ "pointer_bytes": 8
+ },
+ "sections": {
+ "text": 5908,
+ "data": 0,
+ "bss": 0
+ },
+ "members": [
+ "runtime.o",
+ "evaluate.o"
+ ],
+ "external_symbols": [
+ "memcpy",
+ "strlen"
+ ],
+ "size_output": " text\t data\t bss\t dec\t hex\tfilename\n 4988\t 0\t 0\t 4988\t 137c\truntime.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n 920\t 0\t 0\t 920\t 398\tevaluate.o (ex /home/eunhhu/work/pure/prototypes/connections/build/libpure-execution.a)\n",
+ "archive_sha256": "bb5750a47f6f8ac4307dd633d836460d6045347880a6c53df9669e675e49929e",
+ "layout_binary_sha256": "04c008fb7e0b1ecc8435bce6fbc4478de6180a54da6538d8742acb9b51992fe3",
+ "budget_sha256": "e418419db6231305342ea8780149948e0e41e28b3afb937268e80b4695d3d5cd",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "size_tool": "GNU size (GNU Binutils for Debian) 2.44"
+}
diff --git a/prototypes/connections/results/2026-09-24-source-tui/fixed-cli-tui-check.json b/prototypes/connections/results/2026-09-24-source-tui/fixed-cli-tui-check.json
new file mode 100644
index 0000000..49d2f70
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/fixed-cli-tui-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "c0d600fd9b80a5bdeacb4c015d0050ddf3fde6f8a3ff1dd86905e3fcb681fd30",
+ "archive_bytes": 31929,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-source-tui/fixed-cli-tui.tar.gz b/prototypes/connections/results/2026-09-24-source-tui/fixed-cli-tui.tar.gz
new file mode 100644
index 0000000..e576af8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/fixed-cli-tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-source-tui/fixed-tui-profile.json b/prototypes/connections/results/2026-09-24-source-tui/fixed-tui-profile.json
new file mode 100644
index 0000000..1c5a451
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/fixed-tui-profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app, including the bounded document browser. The raised text ceiling reviews its measured 2,541-byte addition; default CLI and core ceilings are unchanged. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS, including 1,024-key browsing, is checked by check_tui.py on the recorded Linux AArch64 host.",
+ "budget_sha256": "4d3097c9ec3c0139cbdd82161a74d610c15d31c6ee5625101410627664f925e7",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "sections": {
+ "text": 31999,
+ "data": 1036,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "45491c3e28193024d6eb77cbd6569ee8b7470d11ec4126ff4515dba116790308"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-source-tui/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-source-tui/pure-source-preview.tar.gz
new file mode 100644
index 0000000..265a111
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-source-tui/source-check.json b/prototypes/connections/results/2026-09-24-source-tui/source-check.json
new file mode 100644
index 0000000..e7569bb
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/source-check.json
@@ -0,0 +1,13 @@
+{
+ "archive_sha256": "6134ff966d09c76134b921008d16b828a349b7031bdf029379de6eea9e745eaa",
+ "archive_bytes": 318619,
+ "source_files": 162,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17 build and host-neutral behavior tests pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-source-tui/source-cli-tui-check.json b/prototypes/connections/results/2026-09-24-source-tui/source-cli-tui-check.json
new file mode 100644
index 0000000..1c3dd89
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/source-cli-tui-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "6b2671f7e2faf91e96ec9c29d03f5087a1e66f26fbfcc93865700a22e90df9de",
+ "archive_bytes": 50942,
+ "selected_hosts": [
+ "pure-edit",
+ "pure-edit-tui"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "extracted native CLI creates and restores the real document",
+ "editing the packaged .pure source changes the executed reply",
+ "relocated source-loaded TUI and CLI share UTF-8, large and many-document paths"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-source-tui/source-cli-tui.tar.gz b/prototypes/connections/results/2026-09-24-source-tui/source-cli-tui.tar.gz
new file mode 100644
index 0000000..0e2e38f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/source-cli-tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-source-tui/tui-profile.json b/prototypes/connections/results/2026-09-24-source-tui/tui-profile.json
new file mode 100644
index 0000000..348807d
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/tui-profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-source-document-terminal-editor",
+ "scope": "Optional source-loaded POSIX terminal editor for the same document app. Includes the runtime .pure parser and bounded document browser. Default core, fixed CLI and fixed TUI do not link the parser. These are Linux AArch64/GCC 14 section regression ceilings, not whole-process RAM; check_tui.py measures the selected whole process separately.",
+ "budget_sha256": "52df1c0a75119edbe0cfd75d6961c1713237146d44a26cd3b2ce096e4d80d624",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui": {
+ "sections": {
+ "text": 48604,
+ "data": 1084,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "e4fb890935f77a7b359163758ce4c44f3710d1a99130a7d883a4f7329a20a70d"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-source-tui/tui.json b/prototypes/connections/results/2026-09-24-source-tui/tui.json
new file mode 100644
index 0000000..184936b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-source-tui/tui.json
@@ -0,0 +1,25 @@
+{
+ "profile": "native-source-document-terminal-editor",
+ "checks": [
+ "source parse and incompatible definitions fail before store creation",
+ "source CLI and TUI read the same document",
+ "changed source field layout drives TUI input encoding",
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, searched, resized and opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1856,
+ "one_mib_peak_rss_kib": 3216,
+ "one_thousand_key_list_peak_rss_kib": 1952,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "e4fb890935f77a7b359163758ce4c44f3710d1a99130a7d883a4f7329a20a70d"
+}
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/cli-check.json b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-check.json
new file mode 100644
index 0000000..d0bb1fc
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-check.json
@@ -0,0 +1,12 @@
+{
+ "archive_sha256": "19573b079d8d28b08aebeb185acd1cdfc66c006f183e955fba156f8d94d3c4c8",
+ "archive_bytes": 14706,
+ "selected_hosts": [
+ "pure-edit-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/cli-http-tui-check.json b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-http-tui-check.json
new file mode 100644
index 0000000..47d26f1
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-http-tui-check.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "9948083ef0b3b4db1d4efbc4991da1887b2b21a33670c435cd364fcada953f56",
+ "archive_bytes": 53385,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/cli-http-tui.tar.gz b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-http-tui.tar.gz
new file mode 100644
index 0000000..5d5c967
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-http-tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/cli-tui-check.json b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-tui-check.json
new file mode 100644
index 0000000..6dfc3e8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-tui-check.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "a497e58e0c8942386f31a3fdbed11f038aa796afb87aff26eeea81871f2465ed",
+ "archive_bytes": 35642,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/cli-tui.tar.gz b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-tui.tar.gz
new file mode 100644
index 0000000..ddcd49f
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/cli-tui.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/cli.tar.gz b/prototypes/connections/results/2026-09-24-terminal-document-list/cli.tar.gz
new file mode 100644
index 0000000..7c121af
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/cli.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/profile.json b/prototypes/connections/results/2026-09-24-terminal-document-list/profile.json
new file mode 100644
index 0000000..a46d089
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app, including the bounded document browser. The raised text ceiling reviews its measured 2,541-byte addition; default CLI and core ceilings are unchanged. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS, including 1,024-key browsing, is checked by check_tui.py on the recorded Linux AArch64 host.",
+ "budget_sha256": "4d3097c9ec3c0139cbdd82161a74d610c15d31c6ee5625101410627664f925e7",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "sections": {
+ "text": 31303,
+ "data": 1036,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "8b831e7582a0872b90c8b8b3dc4d30088393c3a88713a4eae938c8816bdcda68"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/sanitized.json b/prototypes/connections/results/2026-09-24-terminal-document-list/sanitized.json
new file mode 100644
index 0000000..d49a34b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/sanitized.json
@@ -0,0 +1,22 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, resized and last key opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 9856,
+ "one_mib_peak_rss_kib": 11744,
+ "one_thousand_key_list_peak_rss_kib": 9904,
+ "one_mib_peak_rss_limit_kib": 0,
+ "binary_sha256": "4b4b553289e4cec10aa58e0ef5442905f84d2ddef72fa3d36f301825b2b9ac84"
+}
diff --git a/prototypes/connections/results/2026-09-24-terminal-document-list/tui.json b/prototypes/connections/results/2026-09-24-terminal-document-list/tui.json
new file mode 100644
index 0000000..d8d45f8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-terminal-document-list/tui.json
@@ -0,0 +1,22 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "bounded document browser selects keys and protects unsaved draft",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "1,024 real documents listed, resized and last key opened within RSS gate",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1824,
+ "one_mib_peak_rss_kib": 2832,
+ "one_thousand_key_list_peak_rss_kib": 1856,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "8b831e7582a0872b90c8b8b3dc4d30088393c3a88713a4eae938c8816bdcda68"
+}
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/latency-baseline.json b/prototypes/connections/results/2026-09-24-tui-viewport/latency-baseline.json
new file mode 100644
index 0000000..03c1ff9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/latency-baseline.json
@@ -0,0 +1,176 @@
+{
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "terminal": "PTY 24x80, C.UTF-8",
+ "tui_sha256": "6a38883fef9fcfaf0b24516d0ca1b46edb595f988a9f756c030a3a84ef215107",
+ "cli_sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8",
+ "workloads": {
+ "256-byte-ascii": {
+ "document_bytes": 256,
+ "samples": [
+ {
+ "nanoseconds": 42778,
+ "frame_bytes": 467,
+ "frame_sha256": "79ce175afbd5e1168173ac158c7cba370251a226142ec00780e735b7d71de36d"
+ },
+ {
+ "nanoseconds": 32612,
+ "frame_bytes": 468,
+ "frame_sha256": "84aeb3b92beaccfaa8b4b537280122c8aece74222c9ece27a7c2e0a7a5575371"
+ },
+ {
+ "nanoseconds": 28296,
+ "frame_bytes": 469,
+ "frame_sha256": "b04bcefe68401c190b7dab9c3c29bb09cec9f4db6140d285bd2fe09ff0fa5203"
+ },
+ {
+ "nanoseconds": 28074,
+ "frame_bytes": 470,
+ "frame_sha256": "01c628338d94e9cc3371dcdb33d643c6d87d17808e04e388dc0305f2e2bf0a01"
+ },
+ {
+ "nanoseconds": 27944,
+ "frame_bytes": 471,
+ "frame_sha256": "02d4c8ab2f98fe5e99cf17237d3daa75b484472928e4105d241c06c68b082ccc"
+ },
+ {
+ "nanoseconds": 28612,
+ "frame_bytes": 472,
+ "frame_sha256": "825d74dda937507686530ce7acbff1aafcc3c236feb6befa218f2ccbe33d480b"
+ },
+ {
+ "nanoseconds": 32815,
+ "frame_bytes": 473,
+ "frame_sha256": "9458d218e52f093480dccf23b816dac00c5cc5517b4b145820061f98b61d2b32"
+ },
+ {
+ "nanoseconds": 28093,
+ "frame_bytes": 474,
+ "frame_sha256": "02d7602be4f267cdc2db7b853ecfb743dc594c941b9f6a4be9d3262b16d71fda"
+ },
+ {
+ "nanoseconds": 27556,
+ "frame_bytes": 475,
+ "frame_sha256": "21426683adeee1036c8fe02233ab5a8dde1e6f5d2da8f97d67f9b41419c745ca"
+ },
+ {
+ "nanoseconds": 28297,
+ "frame_bytes": 476,
+ "frame_sha256": "d5c581fddffb80146c1b617be580a65f5936c79dc04deeada0c5b90eaa10b193"
+ }
+ ],
+ "median_nanoseconds": 28296
+ },
+ "one-mib-ascii": {
+ "document_bytes": 1048576,
+ "samples": [
+ {
+ "nanoseconds": 15694866,
+ "frame_bytes": 1950,
+ "frame_sha256": "1ee95680f91eda6c69e7b4009274591735b5b9d2825ed2076cf372acc70c613f"
+ },
+ {
+ "nanoseconds": 15542421,
+ "frame_bytes": 1951,
+ "frame_sha256": "5121e7e36f445a218af46da6796e3124997a7e25b652225f25d93b60d5e09b40"
+ },
+ {
+ "nanoseconds": 15586588,
+ "frame_bytes": 1952,
+ "frame_sha256": "c7b503e012baefa46d8663b98a59f1d1faf4d2b3831750f736984e6443245075"
+ },
+ {
+ "nanoseconds": 15921866,
+ "frame_bytes": 1953,
+ "frame_sha256": "b7edf856b10b641faf4825a8444f386f3faf1ac1e1ccf9a187db6f1465b5264b"
+ },
+ {
+ "nanoseconds": 15594088,
+ "frame_bytes": 1954,
+ "frame_sha256": "cbaaf4f2990d9c060f48cf4dd6e6fab3d872c2370302960a893bcd4c13fa4c47"
+ },
+ {
+ "nanoseconds": 15704829,
+ "frame_bytes": 1955,
+ "frame_sha256": "95ce7a29f9dd111a0a319455231b79bcc41fdf897e8db3411a24821c6cc298c6"
+ },
+ {
+ "nanoseconds": 15593014,
+ "frame_bytes": 1956,
+ "frame_sha256": "440d25b06f6d7dda71bd02225191f0f430a4f4278a10d3bb21b56788ccbd62c4"
+ },
+ {
+ "nanoseconds": 15696681,
+ "frame_bytes": 1957,
+ "frame_sha256": "5a0f58e4f0e16194202e3f56608a6411488aa517378abedf8ff428644e63c9cb"
+ },
+ {
+ "nanoseconds": 15719440,
+ "frame_bytes": 1958,
+ "frame_sha256": "4f3d92e9f165d680c4546040e0ac141db54176f6576893d1a24e89053b487b03"
+ },
+ {
+ "nanoseconds": 15660421,
+ "frame_bytes": 1959,
+ "frame_sha256": "ee37bf811fd99378f57715a638fd589d5c518b34dfdc76d973c64203c2ef16f8"
+ }
+ ],
+ "median_nanoseconds": 15677643
+ },
+ "one-mib-utf8": {
+ "document_bytes": 1048572,
+ "samples": [
+ {
+ "nanoseconds": 37168940,
+ "frame_bytes": 2745,
+ "frame_sha256": "e7275636645244ab12463d96a08bacd5c87aec3307bf86f91399ca654531140a"
+ },
+ {
+ "nanoseconds": 37198756,
+ "frame_bytes": 2746,
+ "frame_sha256": "7d183f69c1dce6fee9b86e6b2c10e01f3779b13753fb1c11160de78505f9a8e0"
+ },
+ {
+ "nanoseconds": 37112959,
+ "frame_bytes": 2747,
+ "frame_sha256": "7d0190b9b944eaa7fcd07af573882df6d436a7847e51dca759a65e93d9100c8e"
+ },
+ {
+ "nanoseconds": 37318718,
+ "frame_bytes": 2748,
+ "frame_sha256": "858d20af32237847e72800093ec28e1998e71c22d0991d75011bf661682323e8"
+ },
+ {
+ "nanoseconds": 37213200,
+ "frame_bytes": 2749,
+ "frame_sha256": "2e848f851e174be238ce270f71749536e473c97ad2f075a55aaf020fc5438c77"
+ },
+ {
+ "nanoseconds": 37296497,
+ "frame_bytes": 2750,
+ "frame_sha256": "77d4bb9a8028ea5420435bdbe23b0c188d6f6065a8eda79c6357defb32605be8"
+ },
+ {
+ "nanoseconds": 37084125,
+ "frame_bytes": 2751,
+ "frame_sha256": "18d8fcba8c9d11f0cf44e2171fb613d49e45f94408b4307526fc90bec5b61e5a"
+ },
+ {
+ "nanoseconds": 37309700,
+ "frame_bytes": 2752,
+ "frame_sha256": "977adff244a908e5b59448e1b8075139fbcc7b35410d0d335ad67580d3d54c44"
+ },
+ {
+ "nanoseconds": 37275311,
+ "frame_bytes": 2753,
+ "frame_sha256": "1e6c90831630b4573e9dec18872d26056e6e96d68e2cfcbe7da8102f0ef8b490"
+ },
+ {
+ "nanoseconds": 37298940,
+ "frame_bytes": 2754,
+ "frame_sha256": "b3599665cc5fb2a72f9a582604c5caaeceff475fa2986f3242adfb4799089600"
+ }
+ ],
+ "median_nanoseconds": 37244255
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/latency-current.json b/prototypes/connections/results/2026-09-24-tui-viewport/latency-current.json
new file mode 100644
index 0000000..92f6cd0
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/latency-current.json
@@ -0,0 +1,176 @@
+{
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "terminal": "PTY 24x80, C.UTF-8",
+ "tui_sha256": "4373eab2cdb033ce54b812232c7787a3a572de26e303daa9dd5001489638c899",
+ "cli_sha256": "8b594a7b1a4ae5b33cde5c842ec1e11c79b6368babc08ac2ffea378b38ac24f8",
+ "workloads": {
+ "256-byte-ascii": {
+ "document_bytes": 256,
+ "samples": [
+ {
+ "nanoseconds": 59019,
+ "frame_bytes": 467,
+ "frame_sha256": "79ce175afbd5e1168173ac158c7cba370251a226142ec00780e735b7d71de36d"
+ },
+ {
+ "nanoseconds": 39463,
+ "frame_bytes": 468,
+ "frame_sha256": "84aeb3b92beaccfaa8b4b537280122c8aece74222c9ece27a7c2e0a7a5575371"
+ },
+ {
+ "nanoseconds": 32555,
+ "frame_bytes": 469,
+ "frame_sha256": "b04bcefe68401c190b7dab9c3c29bb09cec9f4db6140d285bd2fe09ff0fa5203"
+ },
+ {
+ "nanoseconds": 30074,
+ "frame_bytes": 470,
+ "frame_sha256": "01c628338d94e9cc3371dcdb33d643c6d87d17808e04e388dc0305f2e2bf0a01"
+ },
+ {
+ "nanoseconds": 26759,
+ "frame_bytes": 471,
+ "frame_sha256": "02d4c8ab2f98fe5e99cf17237d3daa75b484472928e4105d241c06c68b082ccc"
+ },
+ {
+ "nanoseconds": 27667,
+ "frame_bytes": 472,
+ "frame_sha256": "825d74dda937507686530ce7acbff1aafcc3c236feb6befa218f2ccbe33d480b"
+ },
+ {
+ "nanoseconds": 27371,
+ "frame_bytes": 473,
+ "frame_sha256": "9458d218e52f093480dccf23b816dac00c5cc5517b4b145820061f98b61d2b32"
+ },
+ {
+ "nanoseconds": 29278,
+ "frame_bytes": 474,
+ "frame_sha256": "02d7602be4f267cdc2db7b853ecfb743dc594c941b9f6a4be9d3262b16d71fda"
+ },
+ {
+ "nanoseconds": 28167,
+ "frame_bytes": 475,
+ "frame_sha256": "21426683adeee1036c8fe02233ab5a8dde1e6f5d2da8f97d67f9b41419c745ca"
+ },
+ {
+ "nanoseconds": 37815,
+ "frame_bytes": 476,
+ "frame_sha256": "d5c581fddffb80146c1b617be580a65f5936c79dc04deeada0c5b90eaa10b193"
+ }
+ ],
+ "median_nanoseconds": 29676
+ },
+ "one-mib-ascii": {
+ "document_bytes": 1048576,
+ "samples": [
+ {
+ "nanoseconds": 111481,
+ "frame_bytes": 1950,
+ "frame_sha256": "1ee95680f91eda6c69e7b4009274591735b5b9d2825ed2076cf372acc70c613f"
+ },
+ {
+ "nanoseconds": 73685,
+ "frame_bytes": 1951,
+ "frame_sha256": "5121e7e36f445a218af46da6796e3124997a7e25b652225f25d93b60d5e09b40"
+ },
+ {
+ "nanoseconds": 71222,
+ "frame_bytes": 1952,
+ "frame_sha256": "c7b503e012baefa46d8663b98a59f1d1faf4d2b3831750f736984e6443245075"
+ },
+ {
+ "nanoseconds": 69871,
+ "frame_bytes": 1953,
+ "frame_sha256": "b7edf856b10b641faf4825a8444f386f3faf1ac1e1ccf9a187db6f1465b5264b"
+ },
+ {
+ "nanoseconds": 69945,
+ "frame_bytes": 1954,
+ "frame_sha256": "cbaaf4f2990d9c060f48cf4dd6e6fab3d872c2370302960a893bcd4c13fa4c47"
+ },
+ {
+ "nanoseconds": 69833,
+ "frame_bytes": 1955,
+ "frame_sha256": "95ce7a29f9dd111a0a319455231b79bcc41fdf897e8db3411a24821c6cc298c6"
+ },
+ {
+ "nanoseconds": 70259,
+ "frame_bytes": 1956,
+ "frame_sha256": "440d25b06f6d7dda71bd02225191f0f430a4f4278a10d3bb21b56788ccbd62c4"
+ },
+ {
+ "nanoseconds": 69537,
+ "frame_bytes": 1957,
+ "frame_sha256": "5a0f58e4f0e16194202e3f56608a6411488aa517378abedf8ff428644e63c9cb"
+ },
+ {
+ "nanoseconds": 69648,
+ "frame_bytes": 1958,
+ "frame_sha256": "4f3d92e9f165d680c4546040e0ac141db54176f6576893d1a24e89053b487b03"
+ },
+ {
+ "nanoseconds": 70092,
+ "frame_bytes": 1959,
+ "frame_sha256": "ee37bf811fd99378f57715a638fd589d5c518b34dfdc76d973c64203c2ef16f8"
+ }
+ ],
+ "median_nanoseconds": 70018
+ },
+ "one-mib-utf8": {
+ "document_bytes": 1048572,
+ "samples": [
+ {
+ "nanoseconds": 239129,
+ "frame_bytes": 2745,
+ "frame_sha256": "e7275636645244ab12463d96a08bacd5c87aec3307bf86f91399ca654531140a"
+ },
+ {
+ "nanoseconds": 228593,
+ "frame_bytes": 2746,
+ "frame_sha256": "7d183f69c1dce6fee9b86e6b2c10e01f3779b13753fb1c11160de78505f9a8e0"
+ },
+ {
+ "nanoseconds": 227148,
+ "frame_bytes": 2747,
+ "frame_sha256": "7d0190b9b944eaa7fcd07af573882df6d436a7847e51dca759a65e93d9100c8e"
+ },
+ {
+ "nanoseconds": 227500,
+ "frame_bytes": 2748,
+ "frame_sha256": "858d20af32237847e72800093ec28e1998e71c22d0991d75011bf661682323e8"
+ },
+ {
+ "nanoseconds": 237037,
+ "frame_bytes": 2749,
+ "frame_sha256": "2e848f851e174be238ce270f71749536e473c97ad2f075a55aaf020fc5438c77"
+ },
+ {
+ "nanoseconds": 228370,
+ "frame_bytes": 2750,
+ "frame_sha256": "77d4bb9a8028ea5420435bdbe23b0c188d6f6065a8eda79c6357defb32605be8"
+ },
+ {
+ "nanoseconds": 226463,
+ "frame_bytes": 2751,
+ "frame_sha256": "18d8fcba8c9d11f0cf44e2171fb613d49e45f94408b4307526fc90bec5b61e5a"
+ },
+ {
+ "nanoseconds": 261797,
+ "frame_bytes": 2752,
+ "frame_sha256": "977adff244a908e5b59448e1b8075139fbcc7b35410d0d335ad67580d3d54c44"
+ },
+ {
+ "nanoseconds": 272018,
+ "frame_bytes": 2753,
+ "frame_sha256": "1e6c90831630b4573e9dec18872d26056e6e96d68e2cfcbe7da8102f0ef8b490"
+ },
+ {
+ "nanoseconds": 235852,
+ "frame_bytes": 2754,
+ "frame_sha256": "b3599665cc5fb2a72f9a582604c5caaeceff475fa2986f3242adfb4799089600"
+ }
+ ],
+ "median_nanoseconds": 232222
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/package-http-tui.json b/prototypes/connections/results/2026-09-24-tui-viewport/package-http-tui.json
new file mode 100644
index 0000000..2730260
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/package-http-tui.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "270edeb0f897b3ea1eeacc4e89bcff2c45fefbbe77fd1546307298d801a2ed9b",
+ "archive_bytes": 51844,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-connections-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated parser-free HTTP host and CLI share the document",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/package.json b/prototypes/connections/results/2026-09-24-tui-viewport/package.json
new file mode 100644
index 0000000..c16b305
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/package.json
@@ -0,0 +1,14 @@
+{
+ "archive_sha256": "aa29b551905788ec436628fac1cca119fbf783d2c620ead866fd2e842429fb12",
+ "archive_bytes": 34216,
+ "selected_hosts": [
+ "pure-edit-fixed",
+ "pure-edit-tui-fixed"
+ ],
+ "checks": [
+ "relocated archive has only declared files and every file hash matches",
+ "relocated parser-free runner creates and restores a document",
+ "relocated parser-free runner performs revision-checked edits",
+ "relocated terminal editor saves UTF-8 and one MiB documents"
+ ]
+}
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/profile.json b/prototypes/connections/results/2026-09-24-tui-viewport/profile.json
new file mode 100644
index 0000000..84e6783
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/profile.json
@@ -0,0 +1,21 @@
+{
+ "passed": true,
+ "failures": [],
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS is checked by check_tui.py on the recorded Linux AArch64 host.",
+ "budget_sha256": "e378cb302b2a4bcd2ee674af048116f139b214b59f24244d6c825bc71a8e8a31",
+ "platform": "Linux-6.18.39+rpt-rpi-2712-aarch64-with-glibc2.41",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "sections": {
+ "text": 28762,
+ "data": 988,
+ "bss": 24
+ },
+ "needed": [
+ "libc.so.6"
+ ],
+ "sha256": "4373eab2cdb033ce54b812232c7787a3a572de26e303daa9dd5001489638c899"
+ }
+ }
+}
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/pty-flow.json b/prototypes/connections/results/2026-09-24-tui-viewport/pty-flow.json
new file mode 100644
index 0000000..a8b63d4
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/pty-flow.json
@@ -0,0 +1,19 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 1792,
+ "one_mib_peak_rss_kib": 3168,
+ "one_mib_peak_rss_limit_kib": 4096,
+ "binary_sha256": "4373eab2cdb033ce54b812232c7787a3a572de26e303daa9dd5001489638c899"
+}
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/pty-sanitized.json b/prototypes/connections/results/2026-09-24-tui-viewport/pty-sanitized.json
new file mode 100644
index 0000000..218e7d8
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/pty-sanitized.json
@@ -0,0 +1,19 @@
+{
+ "profile": "native-fixed-document-terminal-editor",
+ "checks": [
+ "cursor insertion and save through terminal",
+ "open another key",
+ "UTF-8 codepoint movement, visible redraw and edit",
+ "resize redraw",
+ "external revision conflict preserves draft",
+ "stored multiline and tabbed document survives edit and reopen",
+ "cached viewport preserves vertical movement across many rows",
+ "one MiB document viewport, edit and fresh CLI restore",
+ "one MiB UTF-8 viewport and edit before cached anchor",
+ "terminal mode restored after key and signal exit"
+ ],
+ "small_peak_rss_kib": 9696,
+ "one_mib_peak_rss_kib": 11680,
+ "one_mib_peak_rss_limit_kib": 0,
+ "binary_sha256": "0f1e1a886d3c1617c8aa73e3348892681bae0c1c1428e4b89eac5985410cc988"
+}
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/pure-document-cli-http-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-tui-viewport/pure-document-cli-http-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..3cc8f4a
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/pure-document-cli-http-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-tui-viewport/pure-document-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-tui-viewport/pure-document-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..d8e21cf
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-tui-viewport/pure-document-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/final-native-window.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/final-native-window.json
new file mode 100644
index 0000000..9b952aa
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/final-native-window.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 15600, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 16880, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 18720, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31392, "heap": 20576, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31392, "heap": 22672, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31392, "heap": 24528, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31392, "heap": 25568, "other": 16, "stack": 112}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [47216, 48432, 49712, 51552, 53536, 55632, 57488, 58528], "large_window_rss_kib": 44000, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/line-width-4096.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/line-width-4096.json
new file mode 100644
index 0000000..f595f21
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/line-width-4096.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_line_width": 4096, "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31344, "heap": 13088, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31344, "heap": 15984, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31344, "heap": 17936, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31344, "heap": 20544, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31472, "heap": 23440, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31472, "heap": 25392, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31472, "heap": 28000, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31472, "heap": 30880, "other": 16, "stack": 112}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [46000, 48896, 50848, 53456, 56480, 58432, 61040, 63920], "large_window_rss_kib": 42736, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/mallinfo.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/mallinfo.json
new file mode 100644
index 0000000..9c77082
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/mallinfo.json
@@ -0,0 +1 @@
+{"cli_conflict_preserves_draft": "pass", "definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_malloc_samples_bytes": [{"arena": 5849088, "free": 1371840, "key": "large", "mapped": 1392640, "used": 4477248}, {"arena": 14450688, "free": 5148272, "key": "large_other", "mapped": 606208, "used": 9302416}, {"arena": 16990208, "free": 7444160, "key": "large", "mapped": 606208, "used": 9546048}, {"arena": 16990208, "free": 7217216, "key": "large_other", "mapped": 606208, "used": 9772992}, {"arena": 16990208, "free": 6992480, "key": "large", "mapped": 606208, "used": 9997728}, {"arena": 16990208, "free": 6767584, "key": "large_other", "mapped": 606208, "used": 10222624}, {"arena": 16990208, "free": 6543008, "key": "large", "mapped": 606208, "used": 10447200}, {"arena": 16990208, "free": 6317776, "key": "large_other", "mapped": 606208, "used": 10672432}, {"arena": 16990208, "free": 6092896, "key": "large", "mapped": 606208, "used": 10897312}, {"arena": 16990208, "free": 5867616, "key": "large_other", "mapped": 606208, "used": 11122592}, {"arena": 16990208, "free": 5643472, "key": "large", "mapped": 606208, "used": 11346736}, {"arena": 16990208, "free": 5417776, "key": "large_other", "mapped": 606208, "used": 11572432}, {"arena": 17711104, "free": 5915184, "key": "large", "mapped": 606208, "used": 11795920}, {"arena": 17711104, "free": 5689968, "key": "large_other", "mapped": 606208, "used": 12021136}, {"arena": 17711104, "free": 5465984, "key": "large", "mapped": 606208, "used": 12245120}, {"arena": 17711104, "free": 5236704, "key": "large_other", "mapped": 606208, "used": 12474400}, {"arena": 17711104, "free": 5013232, "key": "large", "mapped": 606208, "used": 12697872}, {"arena": 18759680, "free": 5836384, "key": "large_other", "mapped": 606208, "used": 12923296}, {"arena": 18759680, "free": 5613104, "key": "large", "mapped": 606208, "used": 13146576}, {"arena": 18759680, "free": 5387408, "key": "large_other", "mapped": 606208, "used": 13372272}, {"arena": 18759680, "free": 5163520, "key": "large", "mapped": 606208, "used": 13596160}, {"arena": 19611648, "free": 5790528, "key": "large_other", "mapped": 606208, "used": 13821120}, {"arena": 19611648, "free": 5567040, "key": "large", "mapped": 606208, "used": 14044608}, {"arena": 19611648, "free": 5341600, "key": "large_other", "mapped": 606208, "used": 14270048}, {"arena": 19611648, "free": 5118352, "key": "large", "mapped": 606208, "used": 14493296}, {"arena": 20660224, "free": 5941504, "key": "large_other", "mapped": 606208, "used": 14718720}, {"arena": 20660224, "free": 5717552, "key": "large", "mapped": 606208, "used": 14942672}, {"arena": 20660224, "free": 5492400, "key": "large_other", "mapped": 606208, "used": 15167824}, {"arena": 20660224, "free": 5268896, "key": "large", "mapped": 606208, "used": 15391328}, {"arena": 20660224, "free": 5043504, "key": "large_other", "mapped": 606208, "used": 15616720}, {"arena": 21708800, "free": 5868816, "key": "large", "mapped": 606208, "used": 15839984}, {"arena": 21708800, "free": 5643168, "key": "large_other", "mapped": 606208, "used": 16065632}, {"arena": 21708800, "free": 5419264, "key": "large", "mapped": 606208, "used": 16289536}, {"arena": 21708800, "free": 5194128, "key": "large_other", "mapped": 606208, "used": 16514672}, {"arena": 21708800, "free": 4969600, "key": "large", "mapped": 606208, "used": 16739200}, {"arena": 22806528, "free": 5842912, "key": "large_other", "mapped": 606208, "used": 16963616}, {"arena": 22806528, "free": 5619648, "key": "large", "mapped": 606208, "used": 17186880}, {"arena": 22806528, "free": 5441248, "key": "large_other", "mapped": 606208, "used": 17365280}, {"arena": 22806528, "free": 5217472, "key": "large", "mapped": 606208, "used": 17589056}, {"arena": 23658496, "free": 5843872, "key": "large_other", "mapped": 606208, "used": 17814624}, {"arena": 23658496, "free": 5620592, "key": "large", "mapped": 606208, "used": 18037904}, {"arena": 23658496, "free": 5395136, "key": "large_other", "mapped": 606208, "used": 18263360}, {"arena": 23658496, "free": 5171792, "key": "large", "mapped": 606208, "used": 18486704}, {"arena": 24707072, "free": 5994912, "key": "large_other", "mapped": 606208, "used": 18712160}, {"arena": 24707072, "free": 5770480, "key": "large", "mapped": 606208, "used": 18936592}, {"arena": 24707072, "free": 5545520, "key": "large_other", "mapped": 606208, "used": 19161552}, {"arena": 24707072, "free": 5321792, "key": "large", "mapped": 606208, "used": 19385280}, {"arena": 24707072, "free": 5096368, "key": "large_other", "mapped": 606208, "used": 19610704}, {"arena": 25755648, "free": 5921760, "key": "large", "mapped": 606208, "used": 19833888}, {"arena": 25755648, "free": 5696016, "key": "large_other", "mapped": 606208, "used": 20059632}, {"arena": 25755648, "free": 5471760, "key": "large", "mapped": 606208, "used": 20283888}, {"arena": 25755648, "free": 5247072, "key": "large_other", "mapped": 606208, "used": 20508576}, {"arena": 25755648, "free": 5022720, "key": "large", "mapped": 606208, "used": 20732928}, {"arena": 26853376, "free": 5895392, "key": "large_other", "mapped": 606208, "used": 20957984}, {"arena": 26853376, "free": 5671920, "key": "large", "mapped": 606208, "used": 21181456}, {"arena": 26853376, "free": 5446704, "key": "large_other", "mapped": 606208, "used": 21406672}, {"arena": 26853376, "free": 5222576, "key": "large", "mapped": 606208, "used": 21630800}, {"arena": 27705344, "free": 5849056, "key": "large_other", "mapped": 606208, "used": 21856288}, {"arena": 27705344, "free": 5625392, "key": "large", "mapped": 606208, "used": 22079952}, {"arena": 27705344, "free": 5400048, "key": "large_other", "mapped": 606208, "used": 22305296}, {"arena": 27705344, "free": 5176640, "key": "large", "mapped": 606208, "used": 22528704}, {"arena": 28753920, "free": 5999456, "key": "large_other", "mapped": 606208, "used": 22754464}, {"arena": 28753920, "free": 5775264, "key": "large", "mapped": 606208, "used": 22978656}, {"arena": 28753920, "free": 5550336, "key": "large_other", "mapped": 606208, "used": 23203584}, {"arena": 28753920, "free": 5326416, "key": "large", "mapped": 606208, "used": 23427504}], "large_switch_map_samples_kib": [{"anonymous": 2352, "file": 31280, "heap": 14464, "other": 16, "stack": 112}, {"anonymous": 2352, "file": 31280, "heap": 14928, "other": 16, "stack": 112}, {"anonymous": 2352, "file": 31280, "heap": 16784, "other": 16, "stack": 112}, {"anonymous": 2352, "file": 31280, "heap": 18832, "other": 16, "stack": 112}, {"anonymous": 2352, "file": 31408, "heap": 20736, "other": 16, "stack": 112}, {"anonymous": 2352, "file": 31408, "heap": 22016, "other": 16, "stack": 112}, {"anonymous": 2352, "file": 31408, "heap": 23856, "other": 16, "stack": 112}, {"anonymous": 2352, "file": 31408, "heap": 25712, "other": 16, "stack": 112}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [48224, 48688, 50544, 52592, 54624, 55904, 57744, 59600], "large_window_rss_kib": 44800, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/no-document-undo.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/no-document-undo.json
new file mode 100644
index 0000000..7b8cf24
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/no-document-undo.json
@@ -0,0 +1 @@
+{"cli_conflict_preserves_draft": "pass", "definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31280, "heap": 14576, "other": 16, "stack": 128}, {"anonymous": 1440, "file": 31280, "heap": 15024, "other": 16, "stack": 128}, {"anonymous": 1440, "file": 31280, "heap": 17152, "other": 16, "stack": 128}, {"anonymous": 1440, "file": 31280, "heap": 19008, "other": 16, "stack": 128}, {"anonymous": 1440, "file": 31408, "heap": 20240, "other": 16, "stack": 128}, {"anonymous": 1440, "file": 31408, "heap": 22144, "other": 16, "stack": 128}, {"anonymous": 1440, "file": 31408, "heap": 23984, "other": 16, "stack": 128}, {"anonymous": 1440, "file": 31408, "heap": 26016, "other": 16, "stack": 128}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [47440, 47888, 50016, 51872, 53232, 55136, 56976, 59008], "large_window_rss_kib": 44048, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/no-key-undo.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/no-key-undo.json
new file mode 100644
index 0000000..6009187
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/no-key-undo.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1456, "file": 31280, "heap": 15600, "other": 16, "stack": 112}, {"anonymous": 1456, "file": 31280, "heap": 16784, "other": 16, "stack": 112}, {"anonymous": 1456, "file": 31280, "heap": 18608, "other": 16, "stack": 112}, {"anonymous": 1456, "file": 31280, "heap": 20320, "other": 16, "stack": 112}, {"anonymous": 1456, "file": 31280, "heap": 21488, "other": 16, "stack": 112}, {"anonymous": 1456, "file": 31280, "heap": 23584, "other": 16, "stack": 112}, {"anonymous": 1456, "file": 31280, "heap": 26800, "other": 16, "stack": 112}, {"anonymous": 1456, "file": 31280, "heap": 27344, "other": 16, "stack": 112}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [48464, 49648, 51472, 53184, 54352, 56448, 59664, 60208], "large_window_rss_kib": 44048, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/no-wrap.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/no-wrap.json
new file mode 100644
index 0000000..b51a374
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/no-wrap.json
@@ -0,0 +1 @@
+{"cli_conflict_preserves_draft": "pass", "definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31264, "heap": 13056, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 13904, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 15184, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 17024, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31392, "heap": 19168, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31392, "heap": 20448, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31392, "heap": 22288, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31392, "heap": 24480, "other": 16, "stack": 112}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [45888, 46736, 48016, 49856, 52128, 53408, 55248, 57440], "large_window_rss_kib": 44000, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/replace-view.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/replace-view.json
new file mode 100644
index 0000000..409e1d9
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/replace-view.json
@@ -0,0 +1 @@
+{"cli_conflict_preserves_draft": "pass", "definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_line_width": 80, "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31280, "heap": 14416, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 15632, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 17696, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 19280, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 21248, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 22608, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 24624, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 25968, "other": 16, "stack": 112}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [47264, 48480, 50544, 52128, 54096, 55456, 57472, 58816], "large_window_rss_kib": 44032, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/same-body.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/same-body.json
new file mode 100644
index 0000000..c8b8149
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/same-body.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31280, "heap": 14368, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 16416, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 18512, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 19696, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 21344, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 23104, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 25280, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 26832, "other": 16, "stack": 112}], "large_switch_mode": "same-body", "large_switch_rss_samples_kib": [47216, 49264, 51360, 52544, 54192, 55952, 58128, 59680], "large_window_rss_kib": 44016, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/same-key.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/same-key.json
new file mode 100644
index 0000000..fac529b
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/same-key.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31264, "heap": 14224, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14224, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14224, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14224, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14224, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14240, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14240, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14240, "other": 16, "stack": 112}], "large_switch_mode": "same", "large_switch_rss_samples_kib": [47056, 47056, 47056, 47056, 47056, 47072, 47072, 47072], "large_window_rss_kib": 44016, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/settled-final.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/settled-final.json
new file mode 100644
index 0000000..bdbdd78
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/settled-final.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31328, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31328, "heap": 16336, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31328, "heap": 17600, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31328, "heap": 19776, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31328, "heap": 21872, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31328, "heap": 23056, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31328, "heap": 25184, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31328, "heap": 26432, "other": 16, "stack": 112}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [47280, 49232, 50496, 52672, 54768, 55952, 58080, 59328], "large_switch_settled_map_kib": {"anonymous": 1440, "file": 31456, "heap": 26432, "other": 16, "stack": 112}, "large_switch_settled_rss_kib": 59456, "large_window_rss_kib": 44064, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/skip-text.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/skip-text.json
new file mode 100644
index 0000000..86c3fe7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/skip-text.json
@@ -0,0 +1 @@
+{"cli_conflict_preserves_draft": "pass", "definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31264, "heap": 14384, "other": 16, "stack": 112}], "large_switch_mode": "alternate", "large_switch_rss_samples_kib": [47216, 47216, 47216, 47216, 47216, 47216, 47216, 47216], "large_window_rss_kib": 44000, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-window-memory-analysis/smaps.json b/prototypes/connections/results/2026-09-24-window-memory-analysis/smaps.json
new file mode 100644
index 0000000..1b88acf
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-window-memory-analysis/smaps.json
@@ -0,0 +1 @@
+{"definition_restores_in_new_window": "pass", "empty_document_restore": "pass", "gtk_cli_write": "pass", "http_conflict_preserves_draft": "pass", "invalid_and_external_definition_preserve_draft": "pass", "large_switch_map_samples_kib": [{"anonymous": 1440, "file": 31280, "heap": 14624, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 15328, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 17184, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31280, "heap": 19040, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31408, "heap": 21136, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31408, "heap": 22992, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31408, "heap": 24032, "other": 16, "stack": 112}, {"anonymous": 1440, "file": 31408, "heap": 25920, "other": 16, "stack": 112}], "large_switch_rss_samples_kib": [47472, 48176, 50032, 51888, 54112, 55968, 57008, 58896], "large_window_rss_kib": 44032, "multi_document_switch_preserves_draft": "pass", "native_definition_apply_and_running_output": "pass", "one_mib_document_one_byte_edit": "pass", "partial_read_definition_rejected": "pass", "profile": "optional-native-document-window", "reloaded_definition_installs_without_rewriting_source": "pass", "source_write_failure_preserves_active_definition": "pass", "unchanged_save_keeps_revision": "pass", "unsaved_close_guard": "pass", "utf8_boundary_and_restart": "pass"}
diff --git a/prototypes/connections/results/2026-09-24-work-slot/pure-document-fixed-cli-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-work-slot/pure-document-fixed-cli-linux-aarch64.tar.gz
new file mode 100644
index 0000000..b2f35c3
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-work-slot/pure-document-fixed-cli-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-work-slot/pure-document-fixed-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-work-slot/pure-document-fixed-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..298e8c2
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-work-slot/pure-document-fixed-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-work-slot/pure-document-source-cli-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-work-slot/pure-document-source-cli-linux-aarch64.tar.gz
new file mode 100644
index 0000000..57a22b7
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-work-slot/pure-document-source-cli-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-work-slot/pure-document-source-cli-tui-linux-aarch64.tar.gz b/prototypes/connections/results/2026-09-24-work-slot/pure-document-source-cli-tui-linux-aarch64.tar.gz
new file mode 100644
index 0000000..38ec704
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-work-slot/pure-document-source-cli-tui-linux-aarch64.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-work-slot/pure-source-preview.tar.gz b/prototypes/connections/results/2026-09-24-work-slot/pure-source-preview.tar.gz
new file mode 100644
index 0000000..458b215
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-work-slot/pure-source-preview.tar.gz
Binary files differ
diff --git a/prototypes/connections/results/2026-09-24-work-slot/source-package-check.json b/prototypes/connections/results/2026-09-24-work-slot/source-package-check.json
new file mode 100644
index 0000000..708e0fa
--- /dev/null
+++ b/prototypes/connections/results/2026-09-24-work-slot/source-package-check.json
@@ -0,0 +1,16 @@
+{
+ "archive_sha256": "a1ba85942463f765c1f908f19419969423f3e474e608dc023e8a3d09b61de50f",
+ "archive_bytes": 334267,
+ "source_files": 171,
+ "checks": [
+ "every extracted source file matches the manifest",
+ "clean C17, both real terminal PTY scenarios and fixed/source CLI document RSS checks pass",
+ "source-loaded CLI and parser-free CLI share the real stored document",
+ "editing .pure changes the native source-loaded reply",
+ "clean selected page store exports mixed revisions to the default flat store",
+ "clean one-MiB document fans out to two same-process Pure domains with independent conflict and release",
+ "clean selected page store runs the source-loaded TUI and relocatable CLI+TUI package",
+ "clean Linux release behavior, code, dependency and RSS gates pass",
+ "clean source-loaded terminal editor PTY scenarios pass"
+ ]
+}
diff --git a/prototypes/connections/runtime.c b/prototypes/connections/runtime.c
new file mode 100644
index 0000000..0bfb7bf
--- /dev/null
+++ b/prototypes/connections/runtime.c
@@ -0,0 +1,393 @@
+#include "runtime.h"
+#include <string.h>
+
+#define NONE SIZE_MAX
+enum { FREE, RECEIVING, READY, RUNNING, DONE };
+#ifdef PURE_RUNTIME_METRICS
+#define METRIC(...) do { __VA_ARGS__; } while (0)
+#else
+#define METRIC(...) ((void)0)
+#endif
+
+static PureWork *lookup(PureTicket ticket, bool require_held) {
+ PureRuntime *r = ticket.runtime;
+ if (!r || ticket.slot >= r->capacity || !ticket.generation) return NULL;
+ PureWork *w = &r->work[ticket.slot];
+ if (w->state == FREE || w->generation != ticket.generation ||
+ (require_held && !w->held)) return NULL;
+ return w;
+}
+
+static bool valid_key(const char *key) {
+ if (!key || !*key) return false;
+ size_t n = 0;
+ for (; n <= 64 && key[n]; ++n) {
+ unsigned char c = (unsigned char)key[n];
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') || c == '-' || c == '_')) return false;
+ }
+ return n <= 64;
+}
+
+/* WRITE results are loans from the admitted input, not a second allocation.
+ * Integer offsets avoid relational comparisons between unrelated C pointers. */
+static bool borrowed_reply(PureSpan input, PureSpan reply) {
+ if (!reply.size) return true;
+ if (!input.data || !reply.data) return false;
+ uintptr_t base = (uintptr_t)input.data, start = (uintptr_t)reply.data;
+ return start >= base && start - base <= input.size &&
+ reply.size <= input.size - (start - base);
+}
+
+static void dispose(PureRuntime *r, PureResource *resource) {
+ PureResource old = *resource;
+ *resource = (PureResource){0};
+ if (old.release) {
+ bool running = r->running;
+ r->running = true;
+ old.release(old.allocation, old.allocation_size);
+ r->running = running;
+ }
+}
+
+static void payload_release(PureRuntime *r, PureWork *w);
+
+/* Iteratively retire a chain of forwarded values. An arbitrarily long chain
+ * must not turn completion into recursive stack growth. */
+static void retire(PureRuntime *r, PureWork *w) {
+ while (w && !w->held && !w->pins) {
+ PureTicket parent = w->parent;
+#ifdef PURE_RUNTIME_METRICS
+ bool released_payload = w->charged || w->resource.release || parent.runtime;
+#endif
+ dispose(r, &w->resource);
+ r->retained -= w->charged;
+ METRIC(if (released_payload) ++r->releases);
+ size_t slot = (size_t)(w - r->work);
+ *w = (PureWork){.next = r->free_head};
+ r->free_head = slot;
+ --r->active;
+ if (!parent.runtime) break;
+ r = parent.runtime;
+ w = lookup(parent, false);
+ /* Pins can only be created and removed by the owner-thread core. */
+ if (!w || !w->pins) break;
+ --w->pins;
+ }
+}
+
+static void payload_release(PureRuntime *r, PureWork *w) {
+ PureTicket parent = w->parent;
+#ifdef PURE_RUNTIME_METRICS
+ bool released_payload = w->charged || w->resource.release || parent.runtime;
+#endif
+ dispose(r, &w->resource);
+ r->retained -= w->charged;
+ METRIC(if (released_payload) ++r->releases);
+ w->charged = 0;
+ w->parent = (PureTicket){0};
+ if (parent.runtime) {
+ PureWork *source = lookup(parent, false);
+ if (source && source->pins) { --source->pins; retire(parent.runtime, source); }
+ }
+}
+
+bool pure_runtime_init(PureRuntime *r, PureWork *work, size_t capacity,
+ const void *definition, PureHost host, size_t budget) {
+ if (!r || ((work == NULL) != (capacity == 0))) return false;
+ *r = (PureRuntime){.definition = definition, .host = host, .free_head = NONE,
+ .ready_head = NONE, .ready_tail = NONE,
+ .budget = budget, .accepting = true};
+ return pure_runtime_bind(r, work, capacity);
+}
+
+bool pure_runtime_bind(PureRuntime *r, PureWork *work, size_t capacity) {
+ if (!r || r->running || r->active || r->retained ||
+ r->ready_head != NONE || r->ready_tail != NONE ||
+ ((work == NULL) != (capacity == 0)))
+ return false;
+ r->work = work;
+ r->capacity = capacity;
+ r->free_head = capacity ? 0 : NONE;
+ for (size_t i = 0; i < capacity; ++i)
+ work[i] = (PureWork){.next = i + 1 < capacity ? i + 1 : NONE};
+ return true;
+}
+
+bool pure_runtime_restart(PureRuntime *r, const void *definition, PureHost host, size_t budget) {
+ if (!r || r->running || r->active) return false;
+ r->definition = definition;
+ r->host = host;
+ r->budget = budget;
+ r->accepting = true;
+ return true;
+}
+
+void pure_runtime_stop(PureRuntime *r) { if (r && !r->running) r->accepting = false; }
+
+static PureResult admission(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t bytes) {
+ if (!r || r->running || !valid_key(key) ||
+ (input != PURE_INPUT_READ && input != PURE_INPUT_WRITE) ||
+ (input == PURE_INPUT_READ ? bytes != 0 : expected < 0)) return PURE_INVALID;
+ if (!r->accepting) return PURE_CLOSED;
+ bool missing_effect = input == PURE_INPUT_READ ? !r->host.read : !r->host.write;
+#ifdef PURE_ASYNC_EFFECTS
+ if (missing_effect && !r->async_effects) return PURE_DENIED;
+#else
+ if (missing_effect) return PURE_DENIED;
+#endif
+ if (r->free_head == NONE) return PURE_BUSY;
+ if (r->serial == UINT64_MAX) return PURE_LIMIT;
+ if (bytes > r->budget - r->retained) { METRIC(++r->budget_rejections); return PURE_BUDGET; }
+ return PURE_OK;
+}
+
+static PureTicket occupy(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t bytes, PureResource resource) {
+ size_t slot = r->free_head;
+ PureWork *w = &r->work[slot];
+ r->free_head = w->next;
+ *w = (PureWork){.generation = ++r->serial, .next = NONE, .charged = bytes,
+ .state = RECEIVING, .held = true, .input = input, .expected = expected,
+ .resource = resource};
+ memcpy(w->key, key, strlen(key) + 1);
+ ++r->active;
+ METRIC(++r->accepted);
+ r->retained += bytes;
+ METRIC(if (r->active > r->peak_active) r->peak_active = r->active);
+ METRIC(if (r->retained > r->peak_retained) r->peak_retained = r->retained);
+ return (PureTicket){r, slot, w->generation};
+}
+
+bool pure_runtime_ready(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running || w->state != RECEIVING) return false;
+ PureRuntime *r = ticket.runtime;
+ w->state = READY;
+ if (r->ready_tail == NONE) r->ready_head = ticket.slot;
+ else r->work[r->ready_tail].next = ticket.slot;
+ r->ready_tail = ticket.slot;
+ return true;
+}
+
+PureResult pure_runtime_accept(PureRuntime *r, PureInput input, const char *key,
+ int64_t expected, size_t size, PureTicket *out) {
+ if (!out) return PURE_INVALID;
+ PureResult status = admission(r, input, key, expected, size);
+ if (status != PURE_OK) return status;
+ PureResource resource = {0};
+ if (size) {
+ if (!r->host.allocate) return PURE_ALLOCATION;
+ r->running = true;
+ bool ok = r->host.allocate(r->host.context, size, &resource);
+ r->running = false;
+ if (!ok || !resource.body.data || resource.body.size != size || !resource.release) {
+ dispose(r, &resource);
+ return PURE_ALLOCATION;
+ }
+ }
+ *out = occupy(r, input, key, expected, size, resource);
+ if (input == PURE_INPUT_READ) pure_runtime_ready(*out);
+ return PURE_OK;
+}
+
+unsigned char *pure_runtime_ingress(PureTicket ticket, size_t *size) {
+ PureWork *w = lookup(ticket, true);
+ if (size) *size = 0;
+ if (!w || ticket.runtime->running || w->state != RECEIVING ||
+ w->input != PURE_INPUT_WRITE || w->parent.runtime) return NULL;
+ if (size) *size = w->resource.body.size;
+ return (unsigned char *)w->resource.body.data;
+}
+
+bool pure_runtime_step(PureRuntime *r) {
+ if (!r || r->running || r->ready_head == NONE) return false;
+#ifdef PURE_ASYNC_EFFECTS
+ PureWork *head = &r->work[r->ready_head];
+ if (head->input == PURE_INPUT_READ ? !r->host.read : !r->host.write) return false;
+#endif
+ size_t slot = r->ready_head;
+ PureWork *w = &r->work[slot];
+ r->ready_head = w->next;
+ if (r->ready_head == NONE) r->ready_tail = NONE;
+ w->next = NONE;
+ w->state = RUNNING;
+ r->running = true;
+ PureOutcome outcome = {0};
+ if (w->input == PURE_INPUT_WRITE) {
+ PureSpan reply = {0};
+ outcome.status = r->host.write(r->host.context, r->definition, w->key,
+ w->expected, w->resource.body, &reply,
+ &outcome.revision);
+ if (outcome.status == PURE_OK) {
+ if (borrowed_reply(w->resource.body, reply)) outcome.body = reply;
+ else outcome.status = PURE_STORE_ERROR;
+ }
+ METRIC(if (outcome.status == PURE_OK) ++r->commits;
+ else if (outcome.status == PURE_CONFLICT) ++r->conflicts);
+ } else {
+ outcome.status = r->host.read(r->host.context, r->definition, w->key,
+ r->budget - r->retained, &w->resource, &outcome.revision);
+ if (outcome.status == PURE_OK) {
+ if (w->resource.body.size > r->budget - r->retained) outcome.status = PURE_BUDGET;
+ else if (w->resource.body.size && (!w->resource.body.data || !w->resource.release))
+ outcome.status = PURE_STORE_ERROR;
+ else {
+ w->charged = w->resource.body.size;
+ r->retained += w->charged;
+ METRIC(if (r->retained > r->peak_retained) r->peak_retained = r->retained);
+ outcome.body = w->resource.body;
+ METRIC(++r->gets);
+ }
+ }
+ METRIC(if (outcome.status == PURE_BUDGET) ++r->budget_rejections);
+ }
+ if (outcome.status != PURE_OK || !outcome.body.size) {
+ outcome.body = (PureSpan){0};
+ payload_release(r, w);
+ }
+ METRIC(r->borrowed_output_bytes += outcome.body.size);
+ w->outcome = outcome;
+ w->state = DONE;
+ r->running = false;
+ return true;
+}
+
+#ifdef PURE_ASYNC_EFFECTS
+bool pure_runtime_enable_async(PureRuntime *r) {
+ if (!r || r->running || r->active) return false;
+ r->async_effects = true;
+ return true;
+}
+
+PureTake pure_runtime_take(PureRuntime *r, PureEffect *out) {
+ if (!r || !out || !r->async_effects || r->running || r->ready_head == NONE)
+ return PURE_TAKE_EMPTY;
+ size_t slot = r->ready_head;
+ PureWork *w = &r->work[slot];
+ r->ready_head = w->next;
+ if (r->ready_head == NONE) r->ready_tail = NONE;
+ w->next = NONE;
+ w->state = RUNNING;
+ *out = (PureEffect){.ticket = {r, slot, w->generation}, .input = w->input,
+ .key = w->key, .expected = w->expected,
+ .value = w->resource.body,
+ .available = r->budget - r->retained};
+ return PURE_TAKE_EFFECT;
+}
+
+bool pure_runtime_complete(PureTicket ticket, PureResult status,
+ PureResource *read_resource, PureSpan write_reply,
+ int64_t revision) {
+ PureWork *w = lookup(ticket, false);
+ PureRuntime *r = ticket.runtime;
+ if (!w || r->running || w->state != RUNNING ||
+ (w->input == PURE_INPUT_WRITE && read_resource) ||
+ (w->input == PURE_INPUT_READ && write_reply.size) ||
+ (w->input == PURE_INPUT_WRITE && status == PURE_OK &&
+ !borrowed_reply(w->resource.body, write_reply)) ||
+ (read_resource && !read_resource->release &&
+ (read_resource->body.size || read_resource->allocation))) return false;
+ r->running = true;
+ PureOutcome outcome = {.status = status, .revision = revision};
+ if (w->input == PURE_INPUT_READ) {
+ PureResource acquired = {0};
+ if (read_resource) {
+ acquired = *read_resource;
+ *read_resource = (PureResource){0};
+ }
+ if (outcome.status == PURE_OK) {
+ if (acquired.body.size > r->budget - r->retained)
+ outcome.status = PURE_BUDGET;
+ else if (acquired.body.size && (!acquired.body.data || !acquired.release))
+ outcome.status = PURE_STORE_ERROR;
+ else {
+ w->resource = acquired;
+ acquired = (PureResource){0};
+ w->charged = w->resource.body.size;
+ r->retained += w->charged;
+ METRIC(if (r->retained > r->peak_retained) r->peak_retained = r->retained);
+ outcome.body = w->resource.body;
+ METRIC(++r->gets);
+ }
+ }
+ dispose(r, &acquired);
+ METRIC(if (outcome.status == PURE_BUDGET) ++r->budget_rejections);
+ } else {
+ if (status == PURE_OK) outcome.body = write_reply;
+ METRIC(if (outcome.status == PURE_OK) ++r->commits;
+ else if (outcome.status == PURE_CONFLICT) ++r->conflicts);
+ }
+ if (outcome.status != PURE_OK || !outcome.body.size) {
+ outcome.body = (PureSpan){0};
+ payload_release(r, w);
+ }
+ METRIC(r->borrowed_output_bytes += outcome.body.size);
+ w->outcome = outcome;
+ w->state = DONE;
+ r->running = false;
+ if (!w->held) retire(r, w);
+ return true;
+}
+#endif
+
+bool pure_runtime_result(PureTicket ticket, PureOutcome *out) {
+ PureWork *w = lookup(ticket, true);
+ if (!out || !w || ticket.runtime->running || w->state != DONE) return false;
+ *out = w->outcome;
+ return true;
+}
+
+PureResult pure_runtime_forward(PureTicket source, PureRuntime *r,
+ const char *key, int64_t expected, PureTicket *out) {
+ PureWork *parent = lookup(source, true);
+ if (!out || !parent || source.runtime->running || parent->state != DONE ||
+ parent->outcome.status != PURE_OK) return PURE_INVALID;
+ PureResult status = admission(r, PURE_INPUT_WRITE, key, expected, parent->outcome.body.size);
+ if (status != PURE_OK) return status;
+ if (parent->pins == SIZE_MAX) return PURE_LIMIT;
+ PureTicket ticket = occupy(r, PURE_INPUT_WRITE, key, expected, parent->outcome.body.size,
+ (PureResource){.body = parent->outcome.body});
+ ++parent->pins;
+ r->work[ticket.slot].parent = source;
+ pure_runtime_ready(ticket);
+ *out = ticket;
+ return PURE_OK;
+}
+
+static void unlink_ready(PureRuntime *r, size_t slot) {
+ size_t previous = NONE;
+ for (size_t at = r->ready_head; at != NONE; at = r->work[at].next) {
+ if (at == slot) {
+ if (previous == NONE) r->ready_head = r->work[at].next;
+ else r->work[previous].next = r->work[at].next;
+ if (r->ready_tail == at) r->ready_tail = previous;
+ r->work[at].next = NONE;
+ return;
+ }
+ previous = at;
+ }
+}
+
+bool pure_runtime_cancel(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running || (w->state != RECEIVING && w->state != READY)) return false;
+ if (w->state == READY) unlink_ready(ticket.runtime, ticket.slot);
+ payload_release(ticket.runtime, w);
+ w->outcome = (PureOutcome){.status = PURE_CANCELLED};
+ w->state = DONE;
+ return true;
+}
+
+bool pure_runtime_release(PureTicket ticket) {
+ PureWork *w = lookup(ticket, true);
+ if (!w || ticket.runtime->running) return false;
+ if (w->state == READY) unlink_ready(ticket.runtime, ticket.slot);
+ w->held = false;
+#ifdef PURE_ASYNC_EFFECTS
+ if (w->state == RUNNING) return true;
+#endif
+ retire(ticket.runtime, w);
+ return true;
+}
diff --git a/prototypes/connections/runtime.h b/prototypes/connections/runtime.h
new file mode 100644
index 0000000..0add777
--- /dev/null
+++ b/prototypes/connections/runtime.h
@@ -0,0 +1,147 @@
+#ifndef PURE_RUNTIME_H
+#define PURE_RUNTIME_H
+#include "flow.h"
+#include "result.h"
+#include <stdint.h>
+
+/* The optional metrics profile changes PureRuntime's layout. Give its init
+ * function a distinct link name so mixed-profile objects cannot link quietly. */
+#ifdef PURE_RUNTIME_METRICS
+#define pure_runtime_init pure_runtime_init_metrics
+#endif
+
+/* One owner thread controls admission, payload credits, completion and loans.
+ * An application definition is opaque to this core. Hosts interpret it and
+ * perform effects; no parser, storage, socket or OS type is linked here. */
+typedef struct PureRuntime PureRuntime;
+typedef struct PureWork PureWork;
+typedef struct { PureRuntime *runtime; size_t slot; uint64_t generation; } PureTicket;
+typedef enum { PURE_INPUT_READ, PURE_INPUT_WRITE } PureInput;
+
+/* The host owns this resource until it successfully returns it to the core.
+ * release must end all access and free/unmap allocation exactly once. It runs
+ * while that domain is busy; calls back into the same domain are rejected. */
+typedef struct {
+ PureSpan body;
+ void *allocation;
+ size_t allocation_size;
+ void (*release)(void *allocation, size_t size);
+} PureResource;
+typedef struct {
+ void *context;
+ bool (*allocate)(void *, size_t, PureResource *);
+ PureResult (*read)(void *, const void *definition, const char *,
+ size_t available, PureResource *, int64_t *revision);
+ /* A successful reply may borrow only from input. The runtime retains its
+ * backing until all reply consumers finish. Effect errors publish no reply. */
+ PureResult (*write)(void *, const void *definition, const char *,
+ int64_t expected, PureSpan input, PureSpan *reply,
+ int64_t *revision);
+} PureHost;
+typedef struct { PureResult status; int64_t revision; PureSpan body; } PureOutcome;
+
+/* Caller-provided work slots: no background thread or per-domain heap. These
+ * records are implementation storage, not an ABI or a wire representation. */
+/* Internal storage order packs the fixed key around small flags. This is not
+ * a public ABI; the layout is checked as part of the core cost gate. */
+struct PureWork {
+ PureTicket parent;
+ unsigned state;
+ PureInput input;
+ bool held;
+ char key[65];
+ int64_t expected;
+ PureOutcome outcome;
+ PureResource resource;
+ uint64_t generation;
+ size_t next, charged, pins;
+};
+struct PureRuntime {
+ const void *definition;
+ PureHost host;
+ PureWork *work;
+ size_t capacity, free_head, ready_head, ready_tail;
+ size_t budget, retained;
+#ifdef PURE_RUNTIME_METRICS
+ size_t peak_retained;
+#endif
+ size_t active;
+#ifdef PURE_RUNTIME_METRICS
+ size_t peak_active;
+#endif
+ uint64_t serial;
+#ifdef PURE_RUNTIME_METRICS
+ uint64_t accepted, commits, gets, conflicts, budget_rejections;
+ uint64_t releases, borrowed_output_bytes;
+#endif
+ bool accepting, running, async_effects;
+};
+
+/* Enforce repeated storage cost on 64-bit C hosts, including macOS where the
+ * Linux object-section checker is unavailable. */
+#if SIZE_MAX == UINT64_MAX && UINTPTR_MAX == UINT64_MAX
+_Static_assert(sizeof(PureWork) == 216, "work-slot layout exceeded its reviewed size");
+#ifdef PURE_RUNTIME_METRICS
+_Static_assert(sizeof(PureRuntime) == 192, "metrics domain layout changed");
+#else
+_Static_assert(sizeof(PureRuntime) == 120, "domain layout changed");
+#endif
+#endif
+
+/* Initialize fresh storage once. A NULL work pointer with capacity zero starts
+ * an idle domain; bind work before admission. Use restart, not init, to reuse
+ * a domain so its monotonic ticket sequence survives restart. definition is
+ * host-owned and remains alive until all work has drained. */
+bool pure_runtime_init(PureRuntime *, PureWork *, size_t capacity,
+ const void *definition, PureHost, size_t budget);
+bool pure_runtime_restart(PureRuntime *, const void *definition, PureHost, size_t budget);
+void pure_runtime_stop(PureRuntime *); /* stop admission, allow queued work to drain */
+/* Replace caller-owned work storage only after all tickets and loans retire.
+ * A zero-capacity binding releases idle slot storage without resetting budget,
+ * ticket generation or optional metrics. The caller retains the bound array's life. */
+bool pure_runtime_bind(PureRuntime *, PureWork *, size_t capacity);
+
+/* READ queues immediately. WRITE reserves its slot, budget and host allocation
+ * before returning. Fill ingress then publish once with ready. A partial input
+ * released without ready never executes. On error, out is unchanged. */
+PureResult pure_runtime_accept(PureRuntime *, PureInput, const char *key,
+ int64_t expected, size_t input_size, PureTicket *out);
+unsigned char *pure_runtime_ingress(PureTicket, size_t *size);
+bool pure_runtime_ready(PureTicket);
+bool pure_runtime_step(PureRuntime *); /* execute at most one ready job */
+bool pure_runtime_result(PureTicket, PureOutcome *out);
+
+/* Pin a completed reply and queue it as another domain's WRITE input, with no
+ * allocation, serialization or payload copy. Source may be released as soon
+ * as this succeeds; the core retains its backing until the consumer ends.
+ * Each domain charges its own retained input bytes as admission credits.
+ * Credits across domains are NOT distinct physical memory and must not be summed. */
+PureResult pure_runtime_forward(PureTicket source, PureRuntime *destination,
+ const char *key, int64_t expected, PureTicket *out);
+bool pure_runtime_cancel(PureTicket); /* only before execution; keeps a completion */
+bool pure_runtime_release(PureTicket); /* invalidates caller's ticket, preserves pins */
+
+#ifdef PURE_ASYNC_EFFECTS
+/* Optional owner-thread effect suspension. Enable before accepting work. The
+ * host may complete effects in any order, but must call complete on the owner
+ * thread after workers stop accessing its borrowed spans. An in-flight effect
+ * keeps its input alive even if the caller releases the ticket. Effects
+ * borrowed by take stay valid until completion. */
+typedef enum { PURE_TAKE_EMPTY, PURE_TAKE_EFFECT } PureTake;
+typedef struct {
+ PureTicket ticket;
+ PureInput input;
+ const char *key;
+ int64_t expected;
+ PureSpan value; /* raw ingress for WRITE; empty for READ */
+ size_t available; /* remaining payload credits for READ */
+} PureEffect;
+bool pure_runtime_enable_async(PureRuntime *);
+PureTake pure_runtime_take(PureRuntime *, PureEffect *);
+/* A valid completion consumes read_resource (even on failure); a rejected call
+ * leaves it untouched. write_reply borrows from the retained ingress. */
+bool pure_runtime_complete(PureTicket, PureResult status,
+ PureResource *read_resource, PureSpan write_reply,
+ int64_t revision);
+#endif
+#endif
diff --git a/prototypes/connections/server.c b/prototypes/connections/server.c
new file mode 100644
index 0000000..505bb71
--- /dev/null
+++ b/prototypes/connections/server.c
@@ -0,0 +1,645 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include "program.h"
+#include "store-port.h"
+#ifdef PURE_EMBEDDED_PROGRAM
+#include "embedded-plan.h"
+#endif
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <poll.h>
+#ifdef PURE_HTTP_ASYNC
+#include <pthread.h>
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <unistd.h>
+
+#if defined(PURE_HTTP_ASYNC) && !defined(PURE_ASYNC_EFFECTS)
+#error PURE_HTTP_ASYNC requires PURE_ASYNC_EFFECTS
+#endif
+
+enum { SLOTS = 8, HEADER_LIMIT = 4096, CHUNK = 65536 };
+typedef enum { READING_HEADER, READING_BODY, WRITING, WAITING_EFFECT } Phase;
+typedef struct Server Server;
+#ifdef PURE_HTTP_ASYNC
+typedef enum { JOB_FREE, JOB_QUEUED, JOB_RUNNING, JOB_DONE } JobState;
+typedef struct {
+ PureEffect effect;
+ PureResource resource;
+ PureSpan reply;
+ PureResult status;
+ int64_t revision;
+ JobState state;
+} EffectJob;
+typedef struct { Server *server; PureInput input; } EffectWorker;
+#endif
+typedef struct {
+ int fd;
+ Phase phase;
+ uint64_t deadline;
+ char request[HEADER_LIMIT + 1], response[512], key[65];
+ size_t header_size, body_size, received;
+ unsigned char *body;
+ bool put;
+ int64_t expected;
+ PureTicket ticket;
+ PureTransfer transfer;
+ Server *server;
+} Connection;
+struct Server {
+ const char *path;
+#ifndef PURE_EMBEDDED_PROGRAM
+ PureProgram program;
+#endif
+ PureRuntime runtime;
+ PureWork work[SLOTS];
+ size_t budget, active, peak_active;
+ uint64_t accepted, expired, prefix_copy_bytes;
+ uint64_t timeout_ms;
+ int send_buffer;
+ Connection connections[SLOTS];
+#ifdef PURE_HTTP_ASYNC
+ PureHost effect_host;
+ pthread_t worker[2];
+ EffectWorker worker_context[2];
+ pthread_mutex_t job_mutex;
+ pthread_cond_t job_ready[2];
+ EffectJob jobs[SLOTS];
+ size_t next_job[2];
+ int effect_wake;
+ bool worker_stop;
+#endif
+};
+static volatile sig_atomic_t stopping;
+static volatile sig_atomic_t wake_write = -1;
+static void stop_server(int sig) {
+ (void)sig;
+ int saved_errno = errno;
+ stopping = 1;
+ if (wake_write >= 0) {
+ const char byte = 1;
+ (void)write((int)wake_write, &byte, 1);
+ }
+ errno = saved_errno;
+}
+
+static uint64_t now_ms(void) {
+ struct timespec t;
+ if (clock_gettime(CLOCK_MONOTONIC, &t)) abort();
+ return (uint64_t)t.tv_sec * 1000 + (uint64_t)t.tv_nsec / 1000000;
+}
+
+static bool number(const char *text, uint64_t maximum, uint64_t *value) {
+ if (!*text) return false;
+ uint64_t n = 0;
+ for (; *text; ++text) {
+ if (*text < '0' || *text > '9') return false;
+ unsigned digit = (unsigned)(*text - '0');
+ if (digit > maximum || n > (maximum - digit) / 10) return false;
+ n = n * 10 + digit;
+ }
+ *value = n;
+ return true;
+}
+
+static void release_payload(void *owner) {
+ Connection *c = owner;
+ if (c->ticket.runtime) {
+ bool released = pure_runtime_release(c->ticket);
+ assert(released);
+ (void)released;
+ }
+ c->ticket = (PureTicket){0};
+ c->body = NULL;
+}
+
+static void close_connection(Connection *c) {
+ if (c->fd < 0) return;
+ if (c->transfer.active) pure_transfer_abort(&c->transfer);
+ else release_payload(c);
+ close(c->fd);
+ --c->server->active;
+ *c = (Connection){.fd = -1};
+}
+
+static void respond(Connection *c, int status, const char *reason, const char *error,
+ int64_t revision, PureSpan body) {
+ char tag[80] = "";
+ if (revision > 0) snprintf(tag, sizeof(tag), "ETag: \"%" PRId64 "\"\r\n", revision);
+ int length = snprintf(c->response, sizeof(c->response),
+ "HTTP/1.1 %d %s\r\nContent-Length: %zu\r\nConnection: close\r\n"
+ "Content-Type: application/octet-stream\r\nCache-Control: no-store\r\n"
+ "X-Pure-Error: %s\r\n%s\r\n", status, reason, body.size, error, tag);
+ assert(length > 0 && (size_t)length < sizeof(c->response));
+ c->phase = WRITING;
+ pure_transfer_init(&c->transfer,
+ (PureSpan){(const unsigned char *)c->response, (size_t)length}, body, c, release_payload);
+}
+
+static void fail(Connection *c, int status, const char *reason, const char *error) {
+ /* No outstanding backend access on the owner thread at this point. */
+ release_payload(c);
+ respond(c, status, reason, error, 0, (PureSpan){0});
+}
+
+static void answer(Connection *c, PureOutcome result) {
+ switch (result.status) {
+ case PURE_OK: respond(c, 200, "OK", "none", result.revision, result.body); break;
+ case PURE_NOT_FOUND: fail(c, 404, "Not Found", "not_found"); break;
+ case PURE_CONFLICT:
+ respond(c, 412, "Precondition Failed", "conflict", result.revision, (PureSpan){0}); break;
+ case PURE_BUSY: fail(c, 503, "Service Unavailable", "store_busy"); break;
+ case PURE_BUDGET: fail(c, 503, "Service Unavailable", "payload_budget"); break;
+ case PURE_ALLOCATION: fail(c, 503, "Service Unavailable", "allocation"); break;
+ case PURE_CLOSED: fail(c, 503, "Service Unavailable", "stopped"); break;
+ case PURE_DENIED: fail(c, 403, "Forbidden", "denied"); break;
+ case PURE_LIMIT: fail(c, 413, "Content Too Large", "limit"); break;
+ case PURE_UNCERTAIN: fail(c, 500, "Internal Server Error", "durability_unknown"); break;
+ default: fail(c, 500, "Internal Server Error", "storage"); break;
+ }
+}
+
+#ifdef PURE_HTTP_ASYNC
+/* Immutable reads may run beside one writer; only the write worker touches
+ * the store's temporary-name sequence and publication lock. Runtime and
+ * connections remain on poll's owner thread. Borrowed spans outlive work. */
+static void *effect_worker(void *context) {
+ EffectWorker *worker = context;
+ Server *server = worker->server;
+ PureInput input = worker->input;
+ for (;;) {
+ pthread_mutex_lock(&server->job_mutex);
+ size_t slot = SLOTS;
+ while (slot == SLOTS) {
+ for (size_t offset = 0; offset < SLOTS; ++offset) {
+ size_t candidate = (server->next_job[input] + offset) % SLOTS;
+ if (server->jobs[candidate].state == JOB_QUEUED &&
+ server->jobs[candidate].effect.input == input) {
+ slot = candidate;
+ break;
+ }
+ }
+ if (slot < SLOTS || server->worker_stop) break;
+ pthread_cond_wait(&server->job_ready[input], &server->job_mutex);
+ }
+ if (slot == SLOTS) { pthread_mutex_unlock(&server->job_mutex); return NULL; }
+ EffectJob *job = &server->jobs[slot];
+ server->next_job[input] = (slot + 1) % SLOTS;
+ job->state = JOB_RUNNING;
+ PureEffect effect = job->effect;
+ pthread_mutex_unlock(&server->job_mutex);
+
+ PureResource resource = {0};
+ PureSpan reply = {0};
+ int64_t revision = 0;
+ PureHost host = server->effect_host;
+ PureResult status = effect.input == PURE_INPUT_READ ?
+ host.read(host.context, server->runtime.definition, effect.key,
+ effect.available, &resource, &revision) :
+ host.write(host.context, server->runtime.definition, effect.key,
+ effect.expected, effect.value, &reply, &revision);
+
+ pthread_mutex_lock(&server->job_mutex);
+ job->resource = resource;
+ job->reply = reply;
+ job->revision = revision;
+ job->status = status;
+ job->state = JOB_DONE;
+ pthread_mutex_unlock(&server->job_mutex);
+ const char byte = 1;
+ (void)write(server->effect_wake, &byte, 1);
+ }
+}
+
+static void finish_effects(Server *server) {
+ for (size_t i = 0; i < SLOTS; ++i) {
+ pthread_mutex_lock(&server->job_mutex);
+ EffectJob *job = &server->jobs[i];
+ if (job->state != JOB_DONE) { pthread_mutex_unlock(&server->job_mutex); continue; }
+ PureTicket ticket = job->effect.ticket;
+ PureInput input = job->effect.input;
+ PureResource resource = job->resource;
+ PureSpan reply = job->reply;
+ PureResult status = job->status;
+ int64_t revision = job->revision;
+ *job = (EffectJob){0};
+ pthread_mutex_unlock(&server->job_mutex);
+ if (!pure_runtime_complete(ticket, status,
+ input == PURE_INPUT_READ ? &resource : NULL,
+ reply, revision)) abort();
+ for (size_t j = 0; j < SLOTS; ++j) {
+ Connection *c = &server->connections[j];
+ if (c->fd < 0 || c->phase != WAITING_EFFECT ||
+ c->ticket.slot != ticket.slot || c->ticket.generation != ticket.generation)
+ continue;
+ PureOutcome result;
+ if (!pure_runtime_result(ticket, &result)) abort();
+ c->body = NULL;
+ answer(c, result);
+ break;
+ }
+ }
+}
+#endif
+
+static void run_request(Connection *c) {
+ if (c->put && !pure_runtime_ready(c->ticket)) abort();
+#ifdef PURE_HTTP_ASYNC
+ Server *server = c->server;
+ PureEffect effect;
+ PureTake taken = pure_runtime_take(&server->runtime, &effect);
+ if (taken == PURE_TAKE_EFFECT) {
+ pthread_mutex_lock(&server->job_mutex);
+ EffectJob *job = &server->jobs[effect.ticket.slot];
+ if (job->state != JOB_FREE) abort();
+ *job = (EffectJob){.effect = effect, .state = JOB_QUEUED};
+ pthread_cond_signal(&server->job_ready[effect.input]);
+ pthread_mutex_unlock(&server->job_mutex);
+ c->phase = WAITING_EFFECT;
+ return;
+ }
+ abort();
+#else
+ PureOutcome result;
+ while (!pure_runtime_result(c->ticket, &result))
+ if (!pure_runtime_step(&c->server->runtime)) abort();
+#endif
+ c->body = NULL; /* Core now owns input until all consumers release it. */
+#ifdef PURE_HTTP_ASYNC
+ PureOutcome result;
+ if (!pure_runtime_result(c->ticket, &result)) abort();
+#endif
+ answer(c, result);
+}
+
+/* Deliberately bounded HTTP/1.1 subset: one GET/PUT, Content-Length, close.
+ * No transfer coding, pipelining, trailers, Expect, URL decoding, or proxying. */
+static bool parse_header(Connection *c, size_t end) {
+ for (size_t i = 0; i < end; ++i) {
+ unsigned char b = (unsigned char)c->request[i];
+ if ((b < 32 && b != '\r' && b != '\n' && b != '\t') || b == 127) return false;
+ }
+ char *line = c->request, *next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *path = strchr(line, ' ');
+ if (!path) return false;
+ *path++ = 0;
+ if (strcmp(line, "PUT") == 0) c->put = true;
+ else if (strcmp(line, "GET") != 0) return false;
+ char *version = strchr(path, ' ');
+ if (!version) return false;
+ *version++ = 0;
+ if (strcmp(version, "HTTP/1.1") || strncmp(path, "/objects/", 9)) return false;
+ const char *key = path + 9;
+ size_t key_size = strlen(key);
+ if (!key_size || key_size > 64) return false;
+ for (size_t i = 0; i < key_size; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ memcpy(c->key, key, key_size + 1);
+ bool length_seen = false, condition_seen = false, host_seen = false;
+ line = next + 2;
+ while (*line != '\r') {
+ next = strstr(line, "\r\n");
+ if (!next) return false;
+ *next = 0;
+ char *value = strchr(line, ':');
+ if (!value || value == line) return false;
+ *value++ = 0;
+ for (char *p = line; *p; ++p)
+ if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') ||
+ (*p >= '0' && *p <= '9') || *p == '-')) return false;
+ while (*value == ' ' || *value == '\t') ++value;
+ char *tail = value + strlen(value);
+ while (tail > value && (tail[-1] == ' ' || tail[-1] == '\t')) *--tail = 0;
+ if (strchr(value, '\r') || strchr(value, '\n')) return false;
+ uint64_t n;
+ if (!strcasecmp(line, "Content-Length")) {
+ if (length_seen || !number(value, SIZE_MAX, &n)) return false;
+ length_seen = true;
+ c->body_size = (size_t)n;
+ } else if (!strcasecmp(line, "Host")) {
+ if (host_seen || !*value) return false;
+ host_seen = true;
+ } else if (!strcasecmp(line, "If-Match")) {
+ if (condition_seen || tail - value < 3 || *value != '"' || tail[-1] != '"') return false;
+ tail[-1] = 0;
+ if (!number(value + 1, INT64_MAX, &n) || !n) return false;
+ c->expected = (int64_t)n;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "If-None-Match")) {
+ if (condition_seen || strcmp(value, "*")) return false;
+ c->expected = 0;
+ condition_seen = true;
+ } else if (!strcasecmp(line, "Transfer-Encoding") || !strcasecmp(line, "Expect")) return false;
+ line = next + 2;
+ }
+ return host_seen && (c->put ? length_seen && condition_seen : !condition_seen && c->body_size == 0);
+}
+
+static void read_connection(Connection *c) {
+ if (c->phase == READING_HEADER) {
+ ssize_t n = recv(c->fd, c->request + c->header_size, HEADER_LIMIT - c->header_size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->header_size += (size_t)n;
+ c->request[c->header_size] = 0;
+ /* Scan by byte count, so embedded NUL cannot hide a terminator. */
+ size_t end = 0;
+ for (size_t i = 3; i < c->header_size; ++i)
+ if (!memcmp(c->request + i - 3, "\r\n\r\n", 4)) { end = i + 1; break; }
+ if (!end) {
+ if (c->header_size == HEADER_LIMIT) fail(c, 431, "Request Header Fields Too Large", "headers");
+ return;
+ }
+ size_t prefix = c->header_size - end;
+ if (!parse_header(c, end)) { fail(c, 400, "Bad Request", "request"); return; }
+ if (c->body_size > PURE_OBJECT_LIMIT) { fail(c, 413, "Content Too Large", "limit"); return; }
+ if (prefix > c->body_size) { fail(c, 400, "Bad Request", "extra_body"); return; }
+ PureResult admitted = pure_runtime_accept(&c->server->runtime,
+ c->put ? PURE_INPUT_WRITE : PURE_INPUT_READ, c->key, c->expected, c->body_size, &c->ticket);
+ if (admitted != PURE_OK) { answer(c, (PureOutcome){.status = admitted}); return; }
+ if (!c->put) { run_request(c); return; }
+ c->body = pure_runtime_ingress(c->ticket, NULL);
+ if (prefix) memcpy(c->body, c->request + end, prefix);
+ c->server->prefix_copy_bytes += prefix;
+ c->received = prefix;
+ c->phase = READING_BODY;
+ if (c->received == c->body_size) run_request(c);
+ } else {
+ size_t remaining = c->body_size - c->received;
+ ssize_t n = recv(c->fd, c->body + c->received, remaining < CHUNK ? remaining : CHUNK, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ c->received += (size_t)n;
+ if (c->received == c->body_size) run_request(c);
+ }
+}
+
+static void write_connection(Connection *c) {
+ PureSpan span = pure_transfer_next(&c->transfer, CHUNK);
+ ssize_t n = send(c->fd, span.data, span.size, 0);
+ if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) close_connection(c); return; }
+ if (!n) { close_connection(c); return; }
+ if (!pure_transfer_consume(&c->transfer, (size_t)n)) abort();
+ if (!c->transfer.active) close_connection(c);
+}
+
+static bool nonblocking(int fd) {
+ int flags = fcntl(fd, F_GETFL, 0);
+ return flags >= 0 && fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0;
+}
+
+static bool close_on_exec(int fd) {
+ int flags = fcntl(fd, F_GETFD, 0);
+ return flags >= 0 && fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0;
+}
+
+int main(int argc, char **argv) {
+ Server server = {.budget = 4u * 1024u * 1024u, .timeout_ms = 10000};
+ unsigned port = 8767;
+#ifndef PURE_EMBEDDED_PROGRAM
+ const char *program_path = NULL;
+ bool explain = argc == 3 && !strcmp(argv[1], "--check-program");
+ char program_error[160];
+ if (explain) program_path = argv[2];
+#else
+ bool explain = false;
+#endif
+ for (int i = 1; !explain && i < argc; i += 2) {
+ if (i + 1 == argc) goto usage;
+ uint64_t value;
+ if (!strcmp(argv[i], "--store")) server.path = argv[i + 1];
+#ifndef PURE_EMBEDDED_PROGRAM
+ else if (!strcmp(argv[i], "--program")) program_path = argv[i + 1];
+#endif
+ else if (!strcmp(argv[i], "--port") && number(argv[i + 1], 65535, &value)) port = (unsigned)value;
+ else if (!strcmp(argv[i], "--budget") && number(argv[i + 1], SIZE_MAX, &value) && value) server.budget = (size_t)value;
+ else if (!strcmp(argv[i], "--timeout-ms") && number(argv[i + 1], 3600000, &value) && value) server.timeout_ms = value;
+ else if (!strcmp(argv[i], "--send-buffer") && number(argv[i + 1], INT32_MAX, &value)) server.send_buffer = (int)value;
+ else goto usage;
+ }
+ if (!server.path && !explain) goto usage;
+#ifndef PURE_EMBEDDED_PROGRAM
+ if (!program_path) goto usage;
+ if (!pure_program_load(program_path, &server.program, program_error, sizeof(program_error))) {
+ fprintf(stderr, "Program: %s\n", program_error); return 2;
+ }
+ if (explain) {
+ PureProgram *p = &server.program;
+ printf("{\"read\":{\"to_end\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"write\":{\"to_end\":%s,\"offset\":%zu,\"length\":%zu,\"minimum_source_bytes\":%zu},"
+ "\"reply_input\":%s,\"view_definitions\":%zu,\"range_definitions\":%zu,"
+ "\"runtime_view_steps\":%zu,\"write_step\":%zu,\"reply_step\":%zu,\"prepared_program_bytes\":%zu,\"steps\":[",
+ p->read.to_end ? "true" : "false", p->read.offset, p->read.length, p->read_required,
+ p->write.to_end ? "true" : "false", p->write.offset, p->write.length, p->input_required,
+ p->reply_input ? "true" : "false", p->view_definitions, p->range_definitions,
+ p->input_steps, p->write_step, p->reply_step, sizeof(*p));
+ for (size_t i = 0; i < p->input_steps; ++i) {
+ const PureRangeStep *step = &p->steps[i];
+ printf("%s{\"source_step\":%zu,\"source\":{\"offset\":%zu,\"length\":%zu,\"to_end\":%s},"
+ "\"offset\":{\"value\":%zu,\"from_u32le\":%s},\"length\":{\"value\":%zu,\"from_u32le\":%s}}",
+ i ? "," : "", step->source_step, step->source.offset, step->source.length,
+ step->source.to_end ? "true" : "false", step->offset.value, step->offset.from_u32le ? "true" : "false",
+ step->length.value, step->length.from_u32le ? "true" : "false");
+ }
+ printf("],\"write_effect\":\"%s\",\"splice_offset\":{\"value\":%zu,\"from_u32le\":%s},"
+ "\"splice_remove\":{\"value\":%zu,\"from_u32le\":%s}}\n",
+ p->splice ? "splice" : "write", p->splice_offset.value,
+ p->splice_offset.from_u32le ? "true" : "false", p->splice_remove.value,
+ p->splice_remove.from_u32le ? "true" : "false");
+ return 0;
+ }
+#endif
+ const PureProgram *program =
+#ifdef PURE_EMBEDDED_PROGRAM
+ &pure_embedded_program;
+#else
+ &server.program;
+#endif
+ if (pure_store_init(server.path) != PURE_OK) { fputs("Cannot initialize byte store directory\n", stderr); return 1; }
+ PureHost host = pure_store_host(server.path);
+#ifdef PURE_HTTP_ASYNC
+ server.effect_host = host;
+ host.read = NULL;
+ host.write = NULL;
+#endif
+ if (!pure_runtime_init(&server.runtime, server.work, SLOTS, program,
+ host, server.budget)) return 1;
+#ifdef PURE_HTTP_ASYNC
+ if (!pure_runtime_enable_async(&server.runtime)) abort();
+#endif
+ signal(SIGPIPE, SIG_IGN);
+ int listener = socket(AF_INET, SOCK_STREAM, 0);
+ if (listener < 0) { perror("socket"); return 1; }
+ int one = 1;
+ setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ struct sockaddr_in address = {.sin_family = AF_INET, .sin_port = htons((uint16_t)port),
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK)};
+ if (bind(listener, (struct sockaddr *)&address, sizeof(address)) || listen(listener, SLOTS) || !nonblocking(listener)) {
+ perror("listen"); close(listener); return 1;
+ }
+ socklen_t address_size = sizeof(address);
+ if (getsockname(listener, (struct sockaddr *)&address, &address_size)) { close(listener); return 1; }
+ int wake[2];
+ if (pipe(wake)) { perror("pipe"); close(listener); return 1; }
+ if (!nonblocking(wake[1]) || !close_on_exec(wake[0]) || !close_on_exec(wake[1])
+#ifdef PURE_HTTP_ASYNC
+ || !nonblocking(wake[0])
+#endif
+ ) {
+ perror("wake pipe"); close(wake[0]); close(wake[1]); close(listener); return 1;
+ }
+ wake_write = wake[1];
+ struct sigaction stop_action = {.sa_handler = stop_server};
+ sigemptyset(&stop_action.sa_mask);
+ if (sigaction(SIGINT, &stop_action, NULL) || sigaction(SIGTERM, &stop_action, NULL)) {
+ perror("sigaction"); wake_write = -1;
+ close(wake[0]); close(wake[1]); close(listener); return 1;
+ }
+#ifdef PURE_HTTP_ASYNC
+ server.effect_wake = wake[1];
+ pthread_attr_t worker_attr;
+ if (pthread_mutex_init(&server.job_mutex, NULL) ||
+ pthread_cond_init(&server.job_ready[PURE_INPUT_READ], NULL) ||
+ pthread_cond_init(&server.job_ready[PURE_INPUT_WRITE], NULL) ||
+ pthread_attr_init(&worker_attr) ||
+ pthread_attr_setstacksize(&worker_attr, 128u * 1024u)) {
+ fputs("Cannot initialize bounded storage workers\n", stderr);
+ wake_write = -1;
+ close(wake[0]); close(wake[1]); close(listener); return 1;
+ }
+ size_t workers_started = 0;
+ for (size_t i = 0; i < 2; ++i) {
+ server.worker_context[i] = (EffectWorker){.server = &server, .input = (PureInput)i};
+ if (pthread_create(&server.worker[i], &worker_attr,
+ effect_worker, &server.worker_context[i])) break;
+ ++workers_started;
+ }
+ pthread_attr_destroy(&worker_attr);
+ if (workers_started != 2) {
+ pthread_mutex_lock(&server.job_mutex);
+ server.worker_stop = true;
+ pthread_cond_signal(&server.job_ready[PURE_INPUT_READ]);
+ pthread_cond_signal(&server.job_ready[PURE_INPUT_WRITE]);
+ pthread_mutex_unlock(&server.job_mutex);
+ for (size_t i = 0; i < workers_started; ++i) pthread_join(server.worker[i], NULL);
+ pthread_cond_destroy(&server.job_ready[PURE_INPUT_READ]);
+ pthread_cond_destroy(&server.job_ready[PURE_INPUT_WRITE]);
+ pthread_mutex_destroy(&server.job_mutex);
+ fputs("Cannot start bounded storage workers\n", stderr);
+ wake_write = -1;
+ close(wake[0]); close(wake[1]); close(listener); return 1;
+ }
+#endif
+ for (size_t i = 0; i < SLOTS; ++i) server.connections[i].fd = -1;
+ printf("{\"port\":%u,\"storage\":\"immutable-byte-extents-v1\"}\n", ntohs(address.sin_port));
+ fflush(stdout);
+ while (!stopping) {
+ struct pollfd polls[SLOTS + 2] = {
+ {.fd = server.active < SLOTS ? listener : -1, .events = POLLIN},
+ {.fd = wake[0], .events = POLLIN}
+ };
+ uint64_t nearest_deadline = UINT64_MAX;
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ polls[i + 2] = (struct pollfd){.fd = c->phase == WAITING_EFFECT ? -1 : c->fd,
+ .events = c->phase == WRITING ? POLLOUT : POLLIN};
+ if (c->fd >= 0 && c->deadline < nearest_deadline) nearest_deadline = c->deadline;
+ }
+ int wait_ms = -1;
+ if (nearest_deadline != UINT64_MAX) {
+ uint64_t now = now_ms();
+ uint64_t remaining = nearest_deadline > now ? nearest_deadline - now : 0;
+ wait_ms = remaining > INT_MAX ? INT_MAX : (int)remaining;
+ }
+ int ready = poll(polls, SLOTS + 2, wait_ms);
+ if (ready < 0 && errno != EINTR) { perror("poll"); stopping = 1; }
+#ifdef PURE_HTTP_ASYNC
+ if (polls[1].revents & POLLIN) {
+ char bytes[64];
+ while (read(wake[0], bytes, sizeof(bytes)) > 0) {}
+ }
+ finish_effects(&server);
+#endif
+ uint64_t now = now_ms();
+ for (size_t i = 0; i < SLOTS; ++i) {
+ Connection *c = &server.connections[i];
+ if (c->fd < 0) continue;
+ if (now >= c->deadline) { ++server.expired; close_connection(c); continue; }
+ short events = polls[i + 2].revents;
+ if (events & (POLLERR | POLLNVAL)) { close_connection(c); continue; }
+#ifdef PURE_HTTP_ASYNC
+ if (c->phase == WAITING_EFFECT) continue;
+#endif
+ if (events & (POLLIN | POLLOUT | POLLHUP)) {
+ if (c->phase == WRITING) write_connection(c); else read_connection(c);
+ }
+ }
+ if (!stopping && (polls[0].revents & POLLIN)) {
+ int fd = accept(listener, NULL, NULL);
+ if (fd < 0) continue;
+ if (!nonblocking(fd)) { close(fd); continue; }
+ if (server.send_buffer) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &server.send_buffer, sizeof(server.send_buffer));
+ for (size_t i = 0; i < SLOTS; ++i) if (server.connections[i].fd < 0) {
+ server.connections[i] = (Connection){.fd = fd, .server = &server, .deadline = now_ms() + server.timeout_ms};
+ ++server.active;
+ ++server.accepted;
+ if (server.active > server.peak_active) server.peak_active = server.active;
+ break;
+ }
+ }
+ }
+ close(listener);
+ wake_write = -1;
+#ifndef PURE_HTTP_ASYNC
+ close(wake[0]);
+ close(wake[1]);
+#endif
+ pure_runtime_stop(&server.runtime);
+ for (size_t i = 0; i < SLOTS; ++i) close_connection(&server.connections[i]);
+#ifdef PURE_HTTP_ASYNC
+ pthread_mutex_lock(&server.job_mutex);
+ server.worker_stop = true;
+ pthread_cond_signal(&server.job_ready[PURE_INPUT_READ]);
+ pthread_cond_signal(&server.job_ready[PURE_INPUT_WRITE]);
+ pthread_mutex_unlock(&server.job_mutex);
+ for (size_t i = 0; i < 2; ++i) if (pthread_join(server.worker[i], NULL)) abort();
+ finish_effects(&server);
+ close(wake[0]);
+ close(wake[1]);
+ pthread_cond_destroy(&server.job_ready[PURE_INPUT_READ]);
+ pthread_cond_destroy(&server.job_ready[PURE_INPUT_WRITE]);
+ pthread_mutex_destroy(&server.job_mutex);
+#endif
+ fprintf(stderr, "{\"active\":%zu,\"retained_payload_bytes\":%zu,\"peak_retained_payload_bytes\":%zu,"
+ "\"payload_budget\":%zu,\"peak_connections\":%zu,\"accepted\":%" PRIu64 ",\"commits\":%" PRIu64 ","
+ "\"gets\":%" PRIu64 ",\"conflicts\":%" PRIu64 ",\"budget_rejections\":%" PRIu64 ","
+ "\"expired\":%" PRIu64 ",\"releases\":%" PRIu64 ",\"ingress_prefix_copy_bytes\":%" PRIu64 ","
+ "\"borrowed_output_bytes\":%" PRIu64 ",\"server_structure_bytes\":%zu}\n",
+ server.active, server.runtime.retained, server.runtime.peak_retained, server.budget, server.peak_active,
+ server.accepted, server.runtime.commits, server.runtime.gets, server.runtime.conflicts, server.runtime.budget_rejections,
+ server.expired, server.runtime.releases, server.prefix_copy_bytes, server.runtime.borrowed_output_bytes, sizeof(server));
+ return 0;
+usage:
+#ifdef PURE_EMBEDDED_PROGRAM
+ fputs("pure-connections-fixed --store DIRECTORY [--port 8767] [--budget BYTES] [--timeout-ms 10000] [--send-buffer BYTES]\n", stderr);
+#else
+ fputs("pure-connections --program FILE --store DIRECTORY [--port 8767] [--budget BYTES] [--timeout-ms 10000] [--send-buffer BYTES]\n"
+ "pure-connections --check-program FILE\n", stderr);
+#endif
+ return 2;
+}
diff --git a/prototypes/connections/source-tui-budget.json b/prototypes/connections/source-tui-budget.json
new file mode 100644
index 0000000..31716a4
--- /dev/null
+++ b/prototypes/connections/source-tui-budget.json
@@ -0,0 +1,12 @@
+{
+ "profile": "linux-aarch64-gcc14-source-document-terminal-editor",
+ "binaries": {
+ "pure-edit-tui": {
+ "max_text_bytes": 49152,
+ "max_data_bytes": 1152,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ }
+ },
+ "scope": "Optional source-loaded POSIX terminal editor for the same document app. Includes the runtime .pure parser and bounded document browser. Default core, fixed CLI and fixed TUI do not link the parser. These are Linux AArch64/GCC 14 section regression ceilings, not whole-process RAM; check_tui.py measures the selected whole process separately."
+}
diff --git a/prototypes/connections/store-paged.c b/prototypes/connections/store-paged.c
new file mode 100644
index 0000000..89c0148
--- /dev/null
+++ b/prototypes/connections/store-paged.c
@@ -0,0 +1,529 @@
+#define _DEFAULT_SOURCE
+#include "store.h"
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Selected Linux/16 KiB-page storage experiment. Small values retain the
+ * existing PUREB001 inline file. Large roots name an append-only page
+ * generation. Both forms expose one immutable, contiguous mapped read. */
+enum { PAGE = 16384, INLINE_BYTES = 24, ROOT_BYTES = 48,
+ MAX_PAGES = (PURE_OBJECT_LIMIT + PAGE - 1) / PAGE };
+static const unsigned char magic[8] = {'P','U','R','E','P','0','0','1'};
+static const unsigned char inline_magic[8] = {'P','U','R','E','B','0','0','1'};
+static uint64_t temporary_sequence;
+
+typedef struct {
+ int64_t revision;
+ size_t size;
+ uint64_t generation;
+ uint64_t refs[MAX_PAGES];
+ bool inline_data;
+} Root;
+
+static bool fault(PureStoreStage stage) {
+#ifdef PURE_STORE_TEST
+ if (pure_store_test_fault(stage)) { errno = EIO; return true; }
+#else
+ (void)stage;
+#endif
+ return false;
+}
+
+static bool file_name(const char *key, char name[72]) {
+ if (!key) return false;
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ snprintf(name, 72, "obj-%s", key);
+ return true;
+}
+
+static void segment_name(const char *key, uint64_t generation, char name[96]) {
+ snprintf(name, 96, "dat-%s-%016" PRIx64, key, generation);
+}
+
+static uint64_t decode64(const unsigned char *bytes) {
+ uint64_t value = 0;
+ for (unsigned i = 0; i < 8; ++i) value |= (uint64_t)bytes[i] << (8 * i);
+ return value;
+}
+
+static void encode64(unsigned char *bytes, uint64_t value) {
+ for (unsigned i = 0; i < 8; ++i) bytes[i] = (unsigned char)(value >> (8 * i));
+}
+
+static bool sync_fd(int fd) {
+ int result;
+ do { result = fsync(fd); } while (result && errno == EINTR);
+ return result == 0;
+}
+
+static bool write_bytes(int fd, const unsigned char *bytes, size_t length) {
+ while (length) {
+ ssize_t n = write(fd, bytes, length);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ bytes += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static bool read_bytes(int fd, unsigned char *bytes, size_t length, off_t offset) {
+ while (length) {
+ ssize_t n = pread(fd, bytes, length, offset);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ bytes += (size_t)n;
+ length -= (size_t)n;
+ offset += n;
+ }
+ return true;
+}
+
+static size_t pages(size_t size) { return (size + PAGE - 1) / PAGE; }
+
+static size_t segment_limit(size_t size) {
+ size_t limit = 2 * pages(size) * PAGE;
+#ifdef PURE_STORE_TEST
+ if (limit > 6 * PAGE) limit = 6 * PAGE;
+#else
+ if (limit < 8 * PAGE) limit = 8 * PAGE;
+#endif
+ return limit;
+}
+
+static bool read_root(int fd, Root *root) {
+ struct stat info;
+ unsigned char header[ROOT_BYTES];
+ if (fstat(fd, &info) || !S_ISREG(info.st_mode) ||
+ !read_bytes(fd, header, INLINE_BYTES, 0)) return false;
+ uint64_t revision = decode64(header + 8), size = decode64(header + 16);
+ if (!revision || revision > INT64_MAX || size > PURE_OBJECT_LIMIT) return false;
+ root->revision = (int64_t)revision;
+ root->size = (size_t)size;
+ if (!memcmp(header, inline_magic, sizeof(inline_magic))) {
+ if (info.st_size != (off_t)(INLINE_BYTES + size)) return false;
+ root->inline_data = true;
+ root->generation = 0;
+ return true;
+ }
+ if (memcmp(header, magic, sizeof(magic)) ||
+ !read_bytes(fd, header + INLINE_BYTES, ROOT_BYTES - INLINE_BYTES, INLINE_BYTES)) return false;
+ uint64_t generation = decode64(header + 24), page = decode64(header + 32);
+ uint64_t count = decode64(header + 40);
+ if (!generation || page != PAGE || count != pages((size_t)size) ||
+ info.st_size != (off_t)(ROOT_BYTES + count * 8)) return false;
+ root->inline_data = false;
+ root->generation = generation;
+ unsigned char bytes[MAX_PAGES * 8];
+ if (count && !read_bytes(fd, bytes, (size_t)count * 8, ROOT_BYTES)) return false;
+ for (size_t i = 0; i < (size_t)count; ++i) root->refs[i] = decode64(bytes + i * 8);
+ return true;
+}
+
+static int open_segment(int directory, const char *key, const Root *root, int flags) {
+ char name[96];
+ segment_name(key, root->generation, name);
+ int fd = openat(directory, name, flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK);
+ if (fd < 0) return -1;
+ struct stat info;
+ if (fstat(fd, &info) || !S_ISREG(info.st_mode) || info.st_size < 0) goto bad;
+ for (size_t i = 0; i < pages(root->size); ++i)
+ if (root->refs[i] > (uint64_t)INT64_MAX / PAGE ||
+ (uint64_t)info.st_size / PAGE <= root->refs[i]) goto bad;
+ return fd;
+bad:
+ close(fd);
+ return -1;
+}
+
+static PureResult open_locked(const char *path, bool writer, int *directory, int *lock) {
+ *directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (*directory < 0) return PURE_STORE_ERROR;
+ *lock = openat(*directory, ".writer.lock",
+ (writer ? O_RDWR : O_RDONLY) | O_NOFOLLOW | O_CLOEXEC);
+ struct stat info;
+ if (*lock < 0 || fstat(*lock, &info) || !S_ISREG(info.st_mode)) return PURE_STORE_ERROR;
+ struct flock hold = {.l_type = writer ? F_WRLCK : F_RDLCK, .l_whence = SEEK_SET,
+ .l_start = 0, .l_len = 0};
+ int rc;
+ do { rc = fcntl(*lock, writer ? F_SETLK : F_SETLKW, &hold); }
+ while (rc && errno == EINTR && !writer);
+ if (rc) return writer && (errno == EACCES || errno == EAGAIN) ? PURE_BUSY : PURE_STORE_ERROR;
+ return PURE_OK;
+}
+
+PureResult pure_store_init(const char *path) {
+ if (!path || !*path || sysconf(_SC_PAGESIZE) != PAGE) return PURE_STORE_ERROR;
+ bool created = mkdir(path, 0700) == 0;
+ if (!created && errno != EEXIST) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600);
+ struct stat info;
+ bool ok = lock >= 0 && !fstat(lock, &info) && S_ISREG(info.st_mode) && sync_fd(lock);
+ if (lock >= 0) close(lock);
+ if (ok) ok = sync_fd(directory);
+ close(directory);
+ if (!ok) return PURE_STORE_ERROR;
+ if (created) {
+ char *parent = strdup(path);
+ if (!parent) return PURE_STORE_ERROR;
+ size_t length = strlen(parent);
+ while (length > 1 && parent[length - 1] == '/') parent[--length] = 0;
+ char *slash = strrchr(parent, '/');
+ if (!slash) strcpy(parent, ".");
+ else if (slash == parent) parent[1] = 0;
+ else *slash = 0;
+ int fd = open(parent, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ free(parent);
+ ok = fd >= 0 && sync_fd(fd);
+ if (fd >= 0) close(fd);
+ }
+ return ok ? PURE_OK : PURE_STORE_ERROR;
+}
+
+void pure_store_release(PureStoredView *view) {
+ if (view->mapped_size) munmap(view->mapping, view->mapped_size);
+ *view = (PureStoredView){0};
+}
+
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out) {
+ *out = (PureStoredView){0};
+ char name[72];
+ if (!file_name(key, name)) return PURE_STORE_ERROR;
+ int directory = -1, lock = -1, head = -1, data = -1;
+ PureResult result = open_locked(path, false, &directory, &lock);
+ if (result != PURE_OK) goto finish;
+ head = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (head < 0) { result = errno == ENOENT ? PURE_NOT_FOUND : PURE_STORE_ERROR; goto finish; }
+ Root root;
+ if (!read_root(head, &root)) { result = PURE_STORE_ERROR; goto finish; }
+ if (root.size < minimum || offset > root.size) { result = PURE_LIMIT; goto finish; }
+ if (whole) length = root.size - offset;
+ if (length > root.size - offset) { result = PURE_LIMIT; goto finish; }
+ if (length > available) { result = PURE_BUDGET; goto finish; }
+ if (root.inline_data) {
+ if (length) {
+ size_t start = INLINE_BYTES + offset;
+ size_t aligned = start - start % PAGE;
+ size_t prefix = start - aligned;
+ size_t mapped_size = prefix + length;
+ void *mapped = mmap(NULL, mapped_size, PROT_READ, MAP_PRIVATE, head, (off_t)aligned);
+ if (mapped == MAP_FAILED) { result = PURE_STORE_ERROR; goto finish; }
+ out->mapping = mapped;
+ out->mapped_size = mapped_size;
+ out->body = (PureSpan){(const unsigned char *)mapped + prefix, length};
+ }
+ } else {
+ data = open_segment(directory, key, &root, O_RDONLY);
+ if (data < 0) { result = PURE_STORE_ERROR; goto finish; }
+ if (length) {
+ size_t first = offset / PAGE, count = pages(offset % PAGE + length);
+ size_t mapped_size = count * PAGE;
+ void *base = mmap(NULL, mapped_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (base == MAP_FAILED) { result = PURE_STORE_ERROR; goto finish; }
+ bool valid = true;
+ for (size_t at = 0; at < count;) {
+ size_t run = 1;
+ while (at + run < count && root.refs[first + at + run] ==
+ root.refs[first + at] + run) ++run;
+ void *address = (unsigned char *)base + at * PAGE;
+ void *mapped = mmap(address, run * PAGE, PROT_READ, MAP_PRIVATE | MAP_FIXED,
+ data, (off_t)(root.refs[first + at] * PAGE));
+ if (mapped != address) { valid = false; break; }
+ at += run;
+ }
+ if (!valid) { munmap(base, mapped_size); result = PURE_STORE_ERROR; goto finish; }
+ out->mapping = base;
+ out->mapped_size = mapped_size;
+ out->body = (PureSpan){(const unsigned char *)base + offset % PAGE, length};
+ }
+ }
+ out->revision = root.revision;
+ out->object_size = root.size;
+ result = PURE_OK;
+finish:
+ if (data >= 0) close(data);
+ if (head >= 0) close(head);
+ if (lock >= 0) close(lock);
+ if (directory >= 0) close(directory);
+ return result;
+}
+
+PureResult pure_store_get(const char *path, const char *key, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, 0, 0, true, 0, available, out);
+}
+
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, offset, length, false, 0, available, out);
+}
+
+static bool read_logical(int data, const Root *root, size_t offset,
+ unsigned char *destination, size_t length) {
+ if (root->inline_data)
+ return read_bytes(data, destination, length, (off_t)(INLINE_BYTES + offset));
+ while (length) {
+ size_t page = offset / PAGE, inside = offset % PAGE;
+ size_t n = PAGE - inside < length ? PAGE - inside : length;
+ if (!read_bytes(data, destination, n, (off_t)(root->refs[page] * PAGE + inside))) return false;
+ destination += n;
+ offset += n;
+ length -= n;
+ }
+ return true;
+}
+
+static bool copy_logical(int source, const Root *root, int destination,
+ size_t offset, size_t length) {
+ unsigned char scratch[4096];
+ while (length) {
+ size_t n = length < sizeof(scratch) ? length : sizeof(scratch);
+ if (!read_logical(source, root, offset, scratch, n) ||
+ !write_bytes(destination, scratch, n)) return false;
+ offset += n;
+ length -= n;
+ }
+ return true;
+}
+
+static bool write_full_pages(int old_data, const Root *old, int destination,
+ bool splice, size_t offset, size_t remove, PureSpan body,
+ Root *next) {
+ size_t count = pages(next->size);
+ for (size_t page = 0; page < count; ++page) {
+ unsigned char bytes[PAGE] = {0};
+ size_t start = page * PAGE, end = start + PAGE;
+ if (end > next->size) end = next->size;
+ size_t at = start;
+ while (at < end) {
+ size_t n;
+ if (splice && at < offset) {
+ n = offset - at < end - at ? offset - at : end - at;
+ if (!read_logical(old_data, old, at, bytes + at - start, n)) return false;
+ } else if (at < offset + body.size || !splice) {
+ size_t source = splice ? at - offset : at;
+ n = body.size - source < end - at ? body.size - source : end - at;
+ memcpy(bytes + at - start, body.data + source, n);
+ } else {
+ n = end - at;
+ if (!read_logical(old_data, old, at - body.size + remove,
+ bytes + at - start, n)) return false;
+ }
+ at += n;
+ }
+ if (!write_bytes(destination, bytes, PAGE)) return false;
+ next->refs[page] = page;
+ }
+ return true;
+}
+
+static bool append_patch(int data, const Root *old, Root *next,
+ size_t offset, PureSpan insert) {
+ if (!insert.size) return true;
+ struct stat info;
+ if (fstat(data, &info) || info.st_size < 0 ||
+ (uint64_t)info.st_size > INT64_MAX - PAGE) return false;
+ off_t start = (info.st_size + PAGE - 1) / PAGE * PAGE;
+ if (ftruncate(data, start) || lseek(data, start, SEEK_SET) != start) return false;
+ size_t first = offset / PAGE, end = pages(offset + insert.size);
+ for (size_t page = first; page < end; ++page) {
+ unsigned char bytes[PAGE];
+ if (!read_bytes(data, bytes, PAGE, (off_t)(old->refs[page] * PAGE))) return false;
+ size_t begin = page * PAGE < offset ? offset : page * PAGE;
+ size_t limit = (page + 1) * PAGE > offset + insert.size ?
+ offset + insert.size : (page + 1) * PAGE;
+ memcpy(bytes + begin - page * PAGE, insert.data + begin - offset, limit - begin);
+ if (!write_bytes(data, bytes, PAGE)) return false;
+ next->refs[page] = (uint64_t)start / PAGE + page - first;
+ }
+ return sync_fd(data);
+}
+
+static bool publish_root(int directory, const char *name, Root *next, int64_t *revision,
+ bool *published, int old_data, const Root *old,
+ bool splice, size_t offset, size_t remove, PureSpan body) {
+ char temporary[96] = "";
+ int fd = -1;
+ for (unsigned attempt = 0; attempt < 64; ++attempt) {
+ if (temporary_sequence == UINT64_MAX) break;
+ snprintf(temporary, sizeof(temporary), ".pending-%ld-%" PRIu64,
+ (long)getpid(), ++temporary_sequence);
+ fd = openat(directory, temporary, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
+ if (fd >= 0) break;
+ temporary[0] = 0;
+ if (errno != EEXIST) break;
+ }
+ if (fd < 0) return false;
+ unsigned char bytes[ROOT_BYTES + MAX_PAGES * 8];
+ memcpy(bytes, next->inline_data ? inline_magic : magic, 8);
+ encode64(bytes + 8, (uint64_t)next->revision);
+ encode64(bytes + 16, next->size);
+ bool ok;
+ if (next->inline_data) {
+ ok = write_bytes(fd, bytes, INLINE_BYTES) && !fault(PURE_AFTER_HEADER);
+ if (ok && splice)
+ ok = copy_logical(old_data, old, fd, 0, offset) &&
+ write_bytes(fd, body.data, body.size) &&
+ copy_logical(old_data, old, fd, offset + remove,
+ old->size - offset - remove);
+ else if (ok) ok = write_bytes(fd, body.data, body.size);
+ } else {
+ encode64(bytes + 24, next->generation);
+ encode64(bytes + 32, PAGE);
+ encode64(bytes + 40, pages(next->size));
+ for (size_t i = 0; i < pages(next->size); ++i)
+ encode64(bytes + ROOT_BYTES + i * 8, next->refs[i]);
+ ok = write_bytes(fd, bytes, ROOT_BYTES) && !fault(PURE_AFTER_HEADER) &&
+ write_bytes(fd, bytes + ROOT_BYTES, pages(next->size) * 8);
+ }
+ if (ok) ok = !fault(PURE_BEFORE_FILE_SYNC) && sync_fd(fd);
+ if (close(fd)) ok = false;
+ if (ok) ok = !fault(PURE_BEFORE_RENAME) && !renameat(directory, temporary, directory, name);
+ if (ok) {
+ *published = true;
+ *revision = next->revision;
+ temporary[0] = 0;
+ ok = !fault(PURE_BEFORE_DIR_SYNC) && sync_fd(directory);
+ }
+ if (*temporary) unlinkat(directory, temporary, 0);
+ return ok;
+}
+
+static void collect_old_segments(int directory, const char *key, uint64_t current) {
+ char prefix[72], retained[96];
+ snprintf(prefix, sizeof(prefix), "dat-%s-", key);
+ segment_name(key, current, retained);
+ int copy = dup(directory);
+ if (copy < 0) return;
+ DIR *entries = fdopendir(copy);
+ if (!entries) { close(copy); return; }
+ bool removed = false;
+ struct dirent *entry;
+ size_t prefix_size = strlen(prefix);
+ while ((entry = readdir(entries))) {
+ if (!strncmp(entry->d_name, ".pending-", 9)) {
+ if (!unlinkat(directory, entry->d_name, 0)) removed = true;
+ continue;
+ }
+ if (strncmp(entry->d_name, prefix, prefix_size) ||
+ strlen(entry->d_name + prefix_size) != 16 ||
+ !strcmp(entry->d_name, retained)) continue;
+ bool hexadecimal = true;
+ for (const char *p = entry->d_name + prefix_size; *p; ++p)
+ if (!((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f'))) hexadecimal = false;
+ if (hexadecimal && !unlinkat(directory, entry->d_name, 0)) removed = true;
+ }
+ closedir(entries);
+ if (removed) sync_fd(directory);
+}
+
+static PureResult mutate(const char *path, const char *key, int64_t expected,
+ PureSpan body, bool splice, size_t offset, size_t remove,
+ size_t max_size, int64_t *revision) {
+ *revision = 0;
+ char name[72], new_segment[96] = "";
+ if (!file_name(key, name) || (body.size && !body.data)) return PURE_STORE_ERROR;
+ if (body.size > PURE_OBJECT_LIMIT || max_size > PURE_OBJECT_LIMIT || expected < 0) return PURE_LIMIT;
+ int directory = -1, lock = -1, head = -1, old_data = -1, new_data = -1;
+ Root old = {0}, next = {0};
+ bool published = false, reused_segment = false, owned_segment = false;
+ struct stat info;
+ PureResult result = open_locked(path, true, &directory, &lock);
+ if (result != PURE_OK) goto finish;
+ result = PURE_STORE_ERROR;
+ head = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (head >= 0) {
+ if (!read_root(head, &old)) goto finish;
+ old_data = old.inline_data ? dup(head) : open_segment(directory, key, &old, O_RDWR);
+ if (old_data < 0) goto finish;
+ } else if (errno != ENOENT) goto finish;
+ *revision = old.revision;
+ if (expected != old.revision) { result = PURE_CONFLICT; goto finish; }
+ if (old.revision == INT64_MAX) { result = PURE_LIMIT; goto finish; }
+ size_t result_size = body.size;
+ if (splice) {
+ if (offset > old.size || remove > old.size - offset ||
+ old.size - remove > max_size ||
+ body.size > max_size - (old.size - remove)) { result = PURE_LIMIT; goto finish; }
+ result_size = old.size - remove + body.size;
+ }
+ next = old;
+ next.revision = old.revision + 1;
+ next.size = result_size;
+ next.inline_data = result_size <= PAGE;
+ if (next.inline_data) next.generation = 0;
+ bool patch = old.revision && !old.inline_data && !next.inline_data &&
+ splice && remove == body.size && result_size == old.size;
+ /* A small value retains the existing PUREB001 24-byte header. */
+ if (!next.inline_data && patch && fstat(old_data, &info) == 0 &&
+ info.st_size < (off_t)segment_limit(old.size)) {
+ reused_segment = true;
+ if (!append_patch(old_data, &old, &next, offset, body)) goto finish;
+ } else if (!next.inline_data) {
+ uint64_t candidate = old.generation;
+ for (unsigned attempt = 0; attempt < 64; ++attempt) {
+ if (candidate == UINT64_MAX) goto finish;
+ segment_name(key, ++candidate, new_segment);
+ new_data = openat(directory, new_segment,
+ O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
+ if (new_data >= 0) { owned_segment = true; break; }
+ if (errno != EEXIST) goto finish;
+ }
+ if (new_data < 0) goto finish;
+ next.generation = candidate;
+ if (!write_full_pages(old_data, &old, new_data, splice, offset, remove, body, &next) ||
+ !sync_fd(new_data)) goto finish;
+ /* A new data file's directory entry must survive before the root
+ * can durably name it. */
+ if (!sync_fd(directory)) goto finish;
+ }
+ if (!publish_root(directory, name, &next, revision, &published,
+ old_data, &old, splice, offset, remove, body)) {
+ result = published ? PURE_UNCERTAIN : PURE_STORE_ERROR;
+ goto finish;
+ }
+ result = PURE_OK;
+ /* Readers have mapped each old inode before releasing their shared lock.
+ * A failed cleanup leaks space but cannot invalidate an existing view. */
+ /* An inline-only edit creates no segments. Avoid a directory-wide scan
+ * on the small-object hot path. */
+ if (!reused_segment && (old.generation || next.generation))
+ collect_old_segments(directory, key, next.generation);
+finish:
+ if (new_data >= 0) close(new_data);
+ if (old_data >= 0) close(old_data);
+ if (head >= 0) close(head);
+ if (result != PURE_OK && result != PURE_UNCERTAIN && owned_segment)
+ unlinkat(directory, new_segment, 0);
+ if (lock >= 0) close(lock);
+ if (directory >= 0) close(directory);
+ return result;
+}
+
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ return mutate(path, key, expected, body, false, 0, 0, PURE_OBJECT_LIMIT, revision);
+}
+
+PureResult pure_store_splice(const char *path, const char *key, int64_t expected,
+ size_t offset, size_t remove, PureSpan insert,
+ size_t max_size, int64_t *revision) {
+ return mutate(path, key, expected, insert, true, offset, remove, max_size, revision);
+}
diff --git a/prototypes/connections/store-port.c b/prototypes/connections/store-port.c
new file mode 100644
index 0000000..7bbe682
--- /dev/null
+++ b/prototypes/connections/store-port.c
@@ -0,0 +1,51 @@
+#include "store-port.h"
+#include "store.h"
+#include <stdlib.h>
+#include <sys/mman.h>
+
+static void free_memory(void *data, size_t size) { (void)size; free(data); }
+static void unmap_memory(void *data, size_t size) { if (size) munmap(data, size); }
+
+static bool allocate(void *context, size_t size, PureResource *out) {
+ (void)context;
+ void *data = malloc(size);
+ if (!data) return false;
+ *out = (PureResource){.body = {data, size}, .allocation = data,
+ .allocation_size = size, .release = free_memory};
+ return true;
+}
+
+static PureResult read_value(void *context, const void *definition, const char *key,
+ size_t available, PureResource *out, int64_t *revision) {
+ const PureProgram *program = definition;
+ if (!program) return PURE_INVALID;
+ PureStoredView view = {0};
+ PureRegion region = program->read;
+ PureResult result = pure_store_select(context, key, region.offset, region.length,
+ region.to_end, program->read_required, available, &view);
+ if (result == PURE_OK) {
+ *out = (PureResource){.body = view.body, .allocation = view.mapping,
+ .allocation_size = view.mapped_size, .release = view.mapped_size ? unmap_memory : NULL};
+ *revision = view.revision;
+ }
+ return result;
+}
+
+static PureResult write_value(void *context, const void *definition, const char *key,
+ int64_t expected, PureSpan input, PureSpan *reply,
+ int64_t *revision) {
+ const PureProgram *program = definition;
+ if (!program) return PURE_INVALID;
+ PureSpan value;
+ if (!pure_program_input(program, input, &value, reply)) return PURE_LIMIT;
+ if (!program->splice) return pure_store_put(context, key, expected, value, revision);
+ size_t offset, remove;
+ if (!pure_program_splice(program, input, &offset, &remove)) return PURE_LIMIT;
+ return pure_store_splice(context, key, expected, offset, remove, value,
+ program->splice_limit, revision);
+}
+
+PureHost pure_store_host(const char *path) {
+ return (PureHost){.context = (void *)path, .allocate = allocate,
+ .read = read_value, .write = write_value};
+}
diff --git a/prototypes/connections/store-port.h b/prototypes/connections/store-port.h
new file mode 100644
index 0000000..0b09403
--- /dev/null
+++ b/prototypes/connections/store-port.h
@@ -0,0 +1,7 @@
+#ifndef PURE_STORE_PORT_H
+#define PURE_STORE_PORT_H
+#include "runtime.h"
+#include "program.h"
+/* The path remains alive for the domain's complete lifetime, including pins. */
+PureHost pure_store_host(const char *path);
+#endif
diff --git a/prototypes/connections/store.c b/prototypes/connections/store.c
new file mode 100644
index 0000000..d9b15a9
--- /dev/null
+++ b/prototypes/connections/store.c
@@ -0,0 +1,309 @@
+#if defined(PURE_STORE_CFR_COPY) && defined(__linux__)
+#define _GNU_SOURCE
+#else
+#define _POSIX_C_SOURCE 200809L
+#endif
+#if defined(PURE_STORE_CFR_COPY) && !defined(__linux__)
+#error PURE_STORE_CFR_COPY is a Linux-only selected storage experiment
+#endif
+/* Darwin's strict POSIX namespace hides open flags used by this adapter. */
+#ifdef __APPLE__
+#define _DARWIN_C_SOURCE
+#endif
+#include "store.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Immutable extent envelope: marker, little-endian u64 revision and payload
+ * length, then unchanged caller bytes. Single-threaded control API; cooperating
+ * processes serialize publication using .writer.lock. */
+enum { HEADER_BYTES = 24 };
+static const unsigned char magic[8] = {'P','U','R','E','B','0','0','1'};
+static uint64_t temporary_sequence;
+
+static bool fault(PureStoreStage stage) {
+#ifdef PURE_STORE_TEST
+ if (pure_store_test_fault(stage)) { errno = EIO; return true; }
+#else
+ (void)stage;
+#endif
+ return false;
+}
+
+static bool file_name(const char *key, char name[72]) {
+ if (!key) return false;
+ size_t length = strlen(key);
+ if (!length || length > 64) return false;
+ for (size_t i = 0; i < length; ++i) {
+ char b = key[i];
+ if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') ||
+ (b >= '0' && b <= '9') || b == '-' || b == '_')) return false;
+ }
+ snprintf(name, 72, "obj-%s", key);
+ return true;
+}
+
+static uint64_t decode64(const unsigned char *bytes) {
+ uint64_t value = 0;
+ for (unsigned i = 0; i < 8; ++i) value |= (uint64_t)bytes[i] << (8 * i);
+ return value;
+}
+
+static void encode64(unsigned char *bytes, uint64_t value) {
+ for (unsigned i = 0; i < 8; ++i) bytes[i] = (unsigned char)(value >> (8 * i));
+}
+
+static bool sync_fd(int fd) {
+ int rc;
+ do { rc = fsync(fd); } while (rc && errno == EINTR);
+ return rc == 0;
+}
+
+static bool write_bytes(int fd, const unsigned char *bytes, size_t length) {
+ while (length) {
+ ssize_t n = write(fd, bytes, length);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ bytes += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static bool read_header(int fd, int64_t *revision, size_t *length) {
+ struct stat info;
+ if (fstat(fd, &info) || !S_ISREG(info.st_mode)) return false;
+ unsigned char header[HEADER_BYTES];
+ size_t used = 0;
+ while (used < sizeof(header)) {
+ ssize_t n = pread(fd, header + used, sizeof(header) - used, (off_t)used);
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0) return false;
+ used += (size_t)n;
+ }
+ uint64_t version = decode64(header + 8), size = decode64(header + 16);
+ if (memcmp(header, magic, sizeof(magic)) || !version || version > INT64_MAX ||
+ size > PURE_OBJECT_LIMIT || info.st_size != (off_t)(HEADER_BYTES + size)) return false;
+ *revision = (int64_t)version;
+ *length = (size_t)size;
+ return true;
+}
+
+PureResult pure_store_init(const char *path) {
+ if (!path || !*path) return PURE_STORE_ERROR;
+ bool created = mkdir(path, 0700) == 0;
+ if (!created && errno != EEXIST) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR; /* Never reinterpret an old DB file. */
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600);
+ struct stat info;
+ bool ok = lock >= 0 && fstat(lock, &info) == 0 && S_ISREG(info.st_mode) && sync_fd(lock);
+ if (lock >= 0) close(lock);
+ if (ok) ok = sync_fd(directory);
+ close(directory);
+ if (!ok) return PURE_STORE_ERROR;
+ if (created) {
+ char *parent = strdup(path);
+ if (!parent) return PURE_STORE_ERROR;
+ size_t length = strlen(parent);
+ while (length > 1 && parent[length - 1] == '/') parent[--length] = 0;
+ char *slash = strrchr(parent, '/');
+ if (!slash) strcpy(parent, ".");
+ else if (slash == parent) parent[1] = 0;
+ else *slash = 0;
+ int fd = open(parent, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ free(parent);
+ ok = fd >= 0 && sync_fd(fd);
+ if (fd >= 0) close(fd);
+ }
+ return ok ? PURE_OK : PURE_STORE_ERROR;
+}
+
+void pure_store_release(PureStoredView *view) {
+ if (view->mapped_size) munmap(view->mapping, view->mapped_size);
+ *view = (PureStoredView){0};
+}
+
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out) {
+ *out = (PureStoredView){0};
+ char name[72];
+ if (!file_name(key, name)) return PURE_STORE_ERROR;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int fd = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ int cause = errno;
+ close(directory);
+ if (fd < 0) return cause == ENOENT ? PURE_NOT_FOUND : PURE_STORE_ERROR;
+ int64_t revision;
+ size_t size;
+ PureResult result = PURE_STORE_ERROR;
+ if (!read_header(fd, &revision, &size)) goto finish;
+ if (size < minimum) { result = PURE_LIMIT; goto finish; }
+ if (offset > size) { result = PURE_LIMIT; goto finish; }
+ if (whole) length = size - offset;
+ if (offset > size || length > size - offset) { result = PURE_LIMIT; goto finish; }
+ if (length > available) { result = PURE_BUDGET; goto finish; }
+ if (length) {
+ long page = sysconf(_SC_PAGESIZE);
+ if (page <= 0) goto finish;
+ size_t start = HEADER_BYTES + offset;
+ size_t aligned = start - start % (size_t)page;
+ size_t prefix = start - aligned;
+ size_t mapped_size = prefix + length;
+ void *mapping = mmap(NULL, mapped_size, PROT_READ, MAP_PRIVATE, fd, (off_t)aligned);
+ if (mapping == MAP_FAILED) goto finish;
+ out->mapping = mapping;
+ out->mapped_size = mapped_size;
+ out->body = (PureSpan){(const unsigned char *)mapping + prefix, length};
+ }
+ out->revision = revision;
+ out->object_size = size;
+ result = PURE_OK;
+finish:
+ close(fd); /* The mapping retains this immutable file version after rename. */
+ return result;
+}
+
+PureResult pure_store_get(const char *path, const char *key, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, 0, 0, true, 0, available, out);
+}
+
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out) {
+ return pure_store_select(path, key, offset, length, false, 0, available, out);
+}
+
+static bool copy_extent(int source, int destination, size_t offset, size_t length) {
+#if defined(PURE_STORE_CFR_COPY) && defined(__linux__)
+ /* Opt-in Linux filesystem copy experiment. Keep the POSIX path for
+ * reported unsupported operations and for every non-selected build. */
+ if (length >= 16384) {
+ off_t from = (off_t)(HEADER_BYTES + offset);
+#ifdef PURE_STORE_TEST
+ bool unsupported_after_partial =
+ pure_store_test_fault(PURE_COPY_RANGE_UNSUPPORTED_AFTER_PARTIAL);
+ bool first_copy = true;
+#endif
+ while (length) {
+ ssize_t copied;
+#ifdef PURE_STORE_TEST
+ if (unsupported_after_partial && !first_copy) {
+ errno = EOPNOTSUPP;
+ copied = -1;
+ } else {
+ size_t wanted = unsupported_after_partial && length > 4096 ? 4096 : length;
+ copied = copy_file_range(source, &from, destination, NULL, wanted, 0);
+ }
+ first_copy = false;
+#else
+ copied = copy_file_range(source, &from, destination, NULL, length, 0);
+#endif
+ if (copied > 0) {
+ offset += (size_t)copied;
+ length -= (size_t)copied;
+ continue;
+ }
+ if (copied == 0) return false; /* The immutable source was truncated. */
+ if (errno == EINTR) continue;
+ if (errno != ENOSYS && errno != EOPNOTSUPP && errno != EXDEV &&
+ errno != EINVAL) return false;
+ break; /* Unsupported on this filesystem; finish with read/write. */
+ }
+ }
+#endif
+ unsigned char scratch[4096];
+ while (length) {
+ size_t wanted = length < sizeof(scratch) ? length : sizeof(scratch);
+ ssize_t n = pread(source, scratch, wanted, (off_t)(HEADER_BYTES + offset));
+ if (n < 0 && errno == EINTR) continue;
+ if (n <= 0 || !write_bytes(destination, scratch, (size_t)n)) return false;
+ offset += (size_t)n;
+ length -= (size_t)n;
+ }
+ return true;
+}
+
+static PureResult mutate(const char *path, const char *key, int64_t expected,
+ PureSpan body, bool splice, size_t offset, size_t remove,
+ size_t max_size, int64_t *revision) {
+ *revision = 0;
+ char name[72], temporary[96] = "";
+ if (!file_name(key, name) || (body.size && !body.data)) return PURE_STORE_ERROR;
+ if (body.size > PURE_OBJECT_LIMIT || max_size > PURE_OBJECT_LIMIT || expected < 0) return PURE_LIMIT;
+ int directory = open(path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (directory < 0) return PURE_STORE_ERROR;
+ int lock = openat(directory, ".writer.lock", O_RDWR | O_NOFOLLOW | O_CLOEXEC);
+ int fd = -1, source = -1;
+ size_t old_size = 0, result_size = body.size;
+ PureResult result = PURE_STORE_ERROR;
+ struct stat info;
+ if (lock < 0 || fstat(lock, &info) || !S_ISREG(info.st_mode)) goto finish;
+ struct flock hold = {.l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0};
+ if (fcntl(lock, F_SETLK, &hold)) {
+ if (errno == EACCES || errno == EAGAIN) result = PURE_BUSY;
+ goto finish;
+ }
+ source = openat(directory, name, O_RDONLY | O_NOFOLLOW | O_NONBLOCK | O_CLOEXEC);
+ if (source >= 0) {
+ if (!read_header(source, revision, &old_size)) goto finish;
+ } else if (errno != ENOENT) goto finish;
+ if (*revision != expected) { result = PURE_CONFLICT; goto finish; }
+ if (*revision == INT64_MAX) { result = PURE_LIMIT; goto finish; }
+ if (splice) {
+ if (offset > old_size || remove > old_size - offset ||
+ old_size - remove > max_size ||
+ body.size > max_size - (old_size - remove)) { result = PURE_LIMIT; goto finish; }
+ result_size = old_size - remove + body.size;
+ }
+ for (unsigned attempt = 0; attempt < 64; ++attempt) {
+ if (temporary_sequence == UINT64_MAX) goto finish;
+ snprintf(temporary, sizeof(temporary), ".pending-%ld-%" PRIu64, (long)getpid(), ++temporary_sequence);
+ fd = openat(directory, temporary, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
+ if (fd >= 0) break;
+ temporary[0] = 0; /* Never remove an existing file on a name collision. */
+ if (errno != EEXIST) goto finish;
+ }
+ if (fd < 0) goto finish;
+ unsigned char header[HEADER_BYTES];
+ memcpy(header, magic, sizeof(magic));
+ encode64(header + 8, (uint64_t)*revision + 1);
+ encode64(header + 16, result_size);
+ if (!write_bytes(fd, header, sizeof(header)) || fault(PURE_AFTER_HEADER)) goto finish;
+ if (splice && !copy_extent(source, fd, 0, offset)) goto finish;
+ if (!write_bytes(fd, body.data, body.size)) goto finish;
+ if (splice && !copy_extent(source, fd, offset + remove, old_size - offset - remove)) goto finish;
+ if (fault(PURE_BEFORE_FILE_SYNC) || !sync_fd(fd)) goto finish;
+ int close_result = close(fd);
+ fd = -1;
+ if (close_result || fault(PURE_BEFORE_RENAME) || renameat(directory, temporary, directory, name)) goto finish;
+ temporary[0] = 0; /* Published: a later sync failure does not roll it back. */
+ ++*revision;
+ result = fault(PURE_BEFORE_DIR_SYNC) || !sync_fd(directory) ? PURE_UNCERTAIN : PURE_OK;
+finish:
+ if (fd >= 0) close(fd);
+ if (source >= 0) close(source);
+ if (*temporary) unlinkat(directory, temporary, 0);
+ if (lock >= 0) close(lock);
+ close(directory);
+ return result;
+}
+
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision) {
+ return mutate(path, key, expected, body, false, 0, 0, PURE_OBJECT_LIMIT, revision);
+}
+
+PureResult pure_store_splice(const char *path, const char *key, int64_t expected,
+ size_t offset, size_t remove, PureSpan insert,
+ size_t max_size, int64_t *revision) {
+ return mutate(path, key, expected, insert, true, offset, remove, max_size, revision);
+}
diff --git a/prototypes/connections/store.h b/prototypes/connections/store.h
new file mode 100644
index 0000000..6896360
--- /dev/null
+++ b/prototypes/connections/store.h
@@ -0,0 +1,48 @@
+#ifndef PURE_STORE_H
+#define PURE_STORE_H
+#include "flow.h"
+#include "result.h"
+#include <stdint.h>
+
+#define PURE_OBJECT_LIMIT ((2u * 6u + 32u) * 32768u + 8192u)
+typedef struct {
+ void *mapping;
+ size_t mapped_size, object_size;
+ PureSpan body;
+ int64_t revision;
+} PureStoredView;
+
+PureResult pure_store_init(const char *path);
+PureResult pure_store_get(const char *path, const char *key, size_t available,
+ PureStoredView *out);
+PureResult pure_store_get_range(const char *path, const char *key, size_t offset,
+ size_t length, size_t available, PureStoredView *out);
+/* Inspect once: guards and mapping refer to the same immutable file version.
+ * minimum preserves bounds checks from eliminated intermediate views.
+ * whole selects the suffix starting at offset; otherwise length is exact. */
+PureResult pure_store_select(const char *path, const char *key, size_t offset,
+ size_t length, bool whole, size_t minimum,
+ size_t available, PureStoredView *out);
+void pure_store_release(PureStoredView *);
+PureResult pure_store_put(const char *path, const char *key, int64_t expected,
+ PureSpan body, int64_t *revision);
+/* Atomic byte replacement: retain [0,offset), insert bytes, retain suffix after
+ * remove bytes. Check the expected revision and bounds under the same writer
+ * lock. expected=0 permits creating an empty base (offset=remove=0).
+ * Retained bytes use bounded scratch space or a selected platform file copy;
+ * never assembles a whole new object in application memory. The immutable
+ * file is still rewritten. max_size is the final-body policy from the
+ * prepared app and is checked with the current size under the writer lock. */
+PureResult pure_store_splice(const char *path, const char *key, int64_t expected,
+ size_t offset, size_t remove, PureSpan insert,
+ size_t max_size, int64_t *revision);
+
+/* Fault hooks exist only in the separately built unit-test binary. */
+typedef enum {
+ PURE_AFTER_HEADER, PURE_BEFORE_FILE_SYNC, PURE_BEFORE_RENAME, PURE_BEFORE_DIR_SYNC,
+ PURE_COPY_RANGE_UNSUPPORTED_AFTER_PARTIAL
+} PureStoreStage;
+#ifdef PURE_STORE_TEST
+int pure_store_test_fault(PureStoreStage stage);
+#endif
+#endif
diff --git a/prototypes/connections/test-async-server-gate.c b/prototypes/connections/test-async-server-gate.c
new file mode 100644
index 0000000..1db9816
--- /dev/null
+++ b/prototypes/connections/test-async-server-gate.c
@@ -0,0 +1,21 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Test-only gate at the file sync point. The production server never links
+ * this file or the PURE_STORE_TEST hook. Only the storage worker reaches it. */
+int pure_store_test_fault(PureStoreStage stage) {
+ static int entered;
+ if (stage != PURE_BEFORE_FILE_SYNC || entered) return 0;
+ entered = 1;
+ const char *signal_fd = getenv("PURE_TEST_GATE_SIGNAL_FD");
+ const char *release_fd = getenv("PURE_TEST_GATE_RELEASE_FD");
+ if (!signal_fd || !release_fd) return 0;
+ int signal = atoi(signal_fd), release = atoi(release_fd);
+ const char byte = 1;
+ if (write(signal, &byte, 1) != 1) _exit(91);
+ char released;
+ if (read(release, &released, 1) != 1) _exit(92);
+ return 0;
+}
diff --git a/prototypes/connections/test-async.c b/prototypes/connections/test-async.c
new file mode 100644
index 0000000..6efaf0b
--- /dev/null
+++ b/prototypes/connections/test-async.c
@@ -0,0 +1,330 @@
+#define _POSIX_C_SOURCE 200809L
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <dirent.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CHECK(test) do { if (!(test)) { fprintf(stderr, "line %d: %s\n", __LINE__, #test); exit(1); } } while (0)
+
+static const PureProgram identity = {
+ .read = {.to_end = true}, .write = {.to_end = true},
+ .reply = {.to_end = true}, .reply_input = true
+};
+
+typedef struct {
+ PureEffect effect;
+ const PureProgram *definition;
+ const char *directory;
+ int start, done;
+ PureResult status;
+ PureSpan reply;
+ int64_t revision;
+} Worker;
+
+static void *write_after_signal(void *context) {
+ Worker *worker = context;
+ char byte = 0;
+ if (read(worker->start, &byte, 1) != 1) worker->status = PURE_STORE_ERROR;
+ else {
+ PureHost store = pure_store_host(worker->directory);
+ worker->status = store.write(store.context, worker->definition,
+ worker->effect.key, worker->effect.expected,
+ worker->effect.value, &worker->reply,
+ &worker->revision);
+ }
+ (void)write(worker->done, &byte, 1);
+ return NULL;
+}
+
+static PureHost async_host(const char *directory) {
+ PureHost host = pure_store_host(directory);
+ host.read = NULL;
+ host.write = NULL;
+ return host;
+}
+
+static PureTicket submit(PureRuntime *runtime, const char *key,
+ const void *body, size_t size) {
+ PureTicket ticket;
+ CHECK(pure_runtime_accept(runtime, PURE_INPUT_WRITE, key, 0, size, &ticket) == PURE_OK);
+ if (size) memcpy(pure_runtime_ingress(ticket, NULL), body, size);
+ CHECK(pure_runtime_ready(ticket));
+ return ticket;
+}
+
+static void expect(const char *directory, const char *key, const void *body, size_t size) {
+ PureStoredView view;
+ CHECK(pure_store_get(directory, key, 64, &view) == PURE_OK);
+ CHECK(view.body.size == size && !memcmp(view.body.data, body, size));
+ pure_store_release(&view);
+}
+
+static void worker_and_forward(const char *directory) {
+ PureRuntime source, destination;
+ PureWork source_slots[2], destination_slot[1];
+ CHECK(pure_runtime_init(&source, source_slots, 2, &identity,
+ async_host(directory), 64));
+ PureTicket ignored = {0};
+ CHECK(pure_runtime_accept(&source, PURE_INPUT_WRITE, "denied", 0, 1,
+ &ignored) == PURE_DENIED);
+ CHECK(pure_runtime_enable_async(&source));
+ PureTicket slow = submit(&source, "slow", "alpha", 5);
+ PureTicket fast = submit(&source, "fast", "beta", 4);
+ CHECK(!pure_runtime_step(&source)); /* No synchronous host callback. */
+ PureEffect deferred;
+ CHECK(pure_runtime_take(&source, &deferred) == PURE_TAKE_EFFECT);
+ CHECK(deferred.ticket.generation == slow.generation &&
+ deferred.value.size == 5 && !memcmp(deferred.value.data, "alpha", 5));
+ CHECK(!pure_runtime_cancel(slow));
+ int start_pipe[2], done_pipe[2];
+ CHECK(!pipe(start_pipe) && !pipe(done_pipe));
+ Worker worker = {.effect = deferred, .definition = &identity, .directory = directory,
+ .start = start_pipe[0], .done = done_pipe[1]};
+ pthread_t thread;
+ CHECK(!pthread_create(&thread, NULL, write_after_signal, &worker));
+ CHECK(pure_runtime_release(slow));
+ CHECK(source.active == 2 && source.retained == 9);
+ PureEffect immediate;
+ CHECK(pure_runtime_take(&source, &immediate) == PURE_TAKE_EFFECT);
+ int64_t revision = 0;
+ PureHost store = pure_store_host(directory);
+ PureSpan reply = {0};
+ PureResult written = store.write(store.context, &identity, immediate.key,
+ immediate.expected, immediate.value, &reply, &revision);
+ CHECK(pure_runtime_complete(immediate.ticket, written, NULL, reply, revision));
+ PureOutcome result;
+ CHECK(pure_runtime_result(fast, &result) && result.status == PURE_OK &&
+ result.body.size == 4 && !memcmp(result.body.data, "beta", 4));
+ CHECK(pure_runtime_release(fast));
+ expect(directory, "fast", "beta", 4);
+ PureStoredView absent;
+ CHECK(pure_store_get(directory, "slow", 64, &absent) == PURE_NOT_FOUND);
+ pure_runtime_stop(&source);
+ CHECK(!pure_runtime_restart(&source, &identity, async_host(directory), 64));
+ CHECK(pure_runtime_accept(&source, PURE_INPUT_READ, "fast", 0, 0,
+ &ignored) == PURE_CLOSED);
+ CHECK(write(start_pipe[1], "x", 1) == 1);
+ struct pollfd done = {.fd = done_pipe[0], .events = POLLIN};
+ CHECK(poll(&done, 1, 5000) == 1 && (done.revents & POLLIN));
+ CHECK(!pthread_join(thread, NULL));
+ CHECK(pure_runtime_complete(deferred.ticket, worker.status, NULL,
+ worker.reply, worker.revision));
+ CHECK(!pure_runtime_complete(deferred.ticket, PURE_OK, NULL, (PureSpan){0}, 1));
+ CHECK(!pure_runtime_result(slow, &result)); /* Caller released before I/O ended. */
+ CHECK(source.active == 0 && source.retained == 0 && source.commits == 2);
+ expect(directory, "slow", "alpha", 5);
+ CHECK(!close(start_pipe[0]) && !close(start_pipe[1]) &&
+ !close(done_pipe[0]) && !close(done_pipe[1]));
+ CHECK(pure_runtime_restart(&source, &identity, async_host(directory), 64));
+
+ CHECK(pure_runtime_init(&destination, destination_slot, 1, &identity,
+ async_host(directory), 64));
+ CHECK(pure_runtime_enable_async(&destination));
+ PureTicket read_ticket;
+ CHECK(pure_runtime_accept(&source, PURE_INPUT_READ, "fast", 0, 0,
+ &read_ticket) == PURE_OK);
+ PureEffect read_effect;
+ CHECK(pure_runtime_take(&source, &read_effect) == PURE_TAKE_EFFECT &&
+ read_effect.input == PURE_INPUT_READ);
+ PureResource mapping = {0};
+ revision = 0;
+ PureResult read_status = store.read(store.context, &identity, read_effect.key,
+ read_effect.available, &mapping, &revision);
+ CHECK(pure_runtime_complete(read_effect.ticket, read_status, &mapping,
+ (PureSpan){0}, revision));
+ CHECK(!mapping.allocation);
+ CHECK(pure_runtime_result(read_ticket, &result) && result.status == PURE_OK &&
+ result.body.size == 4);
+ PureTicket forwarded;
+ CHECK(pure_runtime_forward(read_ticket, &destination, "copy", 0,
+ &forwarded) == PURE_OK);
+ const unsigned char *borrowed = result.body.data;
+ CHECK(pure_runtime_release(read_ticket));
+ CHECK(source.active == 1 && source.retained == 4);
+ PureEffect output;
+ CHECK(pure_runtime_take(&destination, &output) == PURE_TAKE_EFFECT);
+ CHECK(output.value.data == borrowed && output.value.size == 4);
+ revision = 0;
+ reply = (PureSpan){0};
+ written = store.write(store.context, &identity, output.key, output.expected,
+ output.value, &reply, &revision);
+ CHECK(pure_runtime_complete(output.ticket, written, NULL, reply, revision));
+ CHECK(pure_runtime_result(forwarded, &result) && result.status == PURE_OK &&
+ result.body.data == borrowed);
+ CHECK(pure_runtime_release(forwarded));
+ CHECK(source.active == 0 && source.retained == 0 &&
+ destination.active == 0 && destination.retained == 0);
+ expect(directory, "copy", "beta", 4);
+}
+
+static void rejection_and_budget(const char *directory) {
+ PureProgram invalid = identity;
+ invalid.input_required = 4;
+ PureRuntime runtime;
+ PureWork slots[2];
+ CHECK(pure_runtime_init(&runtime, slots, 2, &invalid,
+ async_host(directory), 6));
+ CHECK(pure_runtime_enable_async(&runtime));
+ PureTicket rejected = submit(&runtime, "bad", "x", 1);
+ PureEffect effect;
+ CHECK(pure_runtime_take(&runtime, &effect) == PURE_TAKE_EFFECT);
+ PureHost store = pure_store_host(directory);
+ PureSpan reply = {0};
+ int64_t revision = 0;
+ PureResult status = store.write(store.context, &invalid, effect.key,
+ effect.expected, effect.value, &reply, &revision);
+ CHECK(status == PURE_LIMIT);
+ CHECK(pure_runtime_complete(effect.ticket, status, NULL, reply, revision));
+ PureOutcome result;
+ CHECK(pure_runtime_result(rejected, &result) && result.status == PURE_LIMIT);
+ CHECK(!pure_runtime_complete(rejected, PURE_OK, NULL, (PureSpan){0}, 1));
+ CHECK(pure_runtime_release(rejected));
+ CHECK(runtime.active == 0 && runtime.retained == 0);
+
+ CHECK(pure_runtime_restart(&runtime, &identity, async_host(directory), 6));
+ PureTicket cancelled = submit(&runtime, "unused", "x", 1);
+ CHECK(pure_runtime_cancel(cancelled));
+ CHECK(pure_runtime_result(cancelled, &result) && result.status == PURE_CANCELLED);
+ CHECK(pure_runtime_release(cancelled));
+ PureTicket invalid_read;
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_READ, "fast", 0, 0,
+ &invalid_read) == PURE_OK);
+ PureEffect invalid_effect;
+ CHECK(pure_runtime_take(&runtime, &invalid_effect) == PURE_TAKE_EFFECT);
+ PureResource foreign = {.body = {(const unsigned char *)"x", 1}};
+ CHECK(!pure_runtime_complete(invalid_effect.ticket, PURE_OK, &foreign,
+ (PureSpan){0}, 1));
+ CHECK(foreign.body.size == 1 && runtime.active == 1);
+ CHECK(pure_runtime_complete(invalid_effect.ticket, PURE_STORE_ERROR, NULL,
+ (PureSpan){0}, 0));
+ CHECK(pure_runtime_release(invalid_read));
+ PureTicket bad_reply = submit(&runtime, "bad_reply", "x", 1);
+ PureEffect bad_effect;
+ CHECK(pure_runtime_take(&runtime, &bad_effect) == PURE_TAKE_EFFECT);
+ CHECK(!pure_runtime_complete(bad_effect.ticket, PURE_OK, NULL,
+ (PureSpan){(const unsigned char *)"outside", 7}, 1));
+ CHECK(runtime.active == 1 && runtime.retained == 1);
+ CHECK(pure_runtime_complete(bad_effect.ticket, PURE_STORE_ERROR, NULL,
+ (PureSpan){0}, 0));
+ CHECK(pure_runtime_release(bad_reply) && runtime.active == 0 && runtime.retained == 0);
+ PureTicket first, second;
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_READ, "fast", 0, 0, &first) == PURE_OK);
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_READ, "fast", 0, 0, &second) == PURE_OK);
+ PureEffect one, two;
+ CHECK(pure_runtime_take(&runtime, &one) == PURE_TAKE_EFFECT);
+ CHECK(pure_runtime_take(&runtime, &two) == PURE_TAKE_EFFECT);
+ CHECK(pure_runtime_take(&runtime, &effect) == PURE_TAKE_EMPTY);
+ PureResource a = {0}, b = {0};
+ int64_t revision_a = 0, revision_b = 0;
+ CHECK(store.read(store.context, &identity, one.key, one.available,
+ &a, &revision_a) == PURE_OK);
+ CHECK(store.read(store.context, &identity, two.key, two.available,
+ &b, &revision_b) == PURE_OK);
+ CHECK(pure_runtime_complete(two.ticket, PURE_OK, &b, (PureSpan){0}, revision_b));
+ CHECK(!b.allocation);
+ CHECK(pure_runtime_complete(one.ticket, PURE_OK, &a, (PureSpan){0}, revision_a));
+ CHECK(!a.allocation);
+ CHECK(pure_runtime_result(first, &result) && result.status == PURE_BUDGET);
+ CHECK(pure_runtime_result(second, &result) && result.status == PURE_OK);
+ CHECK(runtime.budget_rejections == 1 && runtime.retained == 4);
+ CHECK(pure_runtime_release(first) && pure_runtime_release(second));
+ CHECK(runtime.active == 0 && runtime.retained == 0);
+}
+
+static void authored_document(const char *directory) {
+ PureProgram program;
+ char error[160];
+ CHECK(pure_program_load("examples/editor.pure", &program, error, sizeof(error)));
+ PureRuntime runtime;
+ PureWork slot[1];
+ CHECK(pure_runtime_init(&runtime, slot, 1, &program,
+ async_host(directory), 64));
+ CHECK(pure_runtime_enable_async(&runtime));
+ const unsigned char create[] = {0,0,0,0, 0,0,0,0, 'H','i'};
+ PureTicket ticket = submit(&runtime, "document", create, sizeof(create));
+ PureEffect effect;
+ CHECK(pure_runtime_take(&runtime, &effect) == PURE_TAKE_EFFECT &&
+ effect.value.size == sizeof(create));
+ PureSpan value, reply = {0};
+ size_t offset, remove;
+ CHECK(pure_program_splice(&program, effect.value, &offset, &remove) &&
+ pure_program_input(&program, effect.value, &value, &reply) &&
+ offset == 0 && remove == 0 && value.size == 2 &&
+ !memcmp(value.data, "Hi", 2));
+ PureHost store = pure_store_host(directory);
+ int64_t revision = 0;
+ PureResult status = store.write(store.context, &program, effect.key,
+ effect.expected, effect.value, &reply, &revision);
+ CHECK(pure_runtime_complete(effect.ticket, status, NULL, reply, revision));
+ PureOutcome result;
+ CHECK(pure_runtime_result(ticket, &result) && result.status == PURE_OK &&
+ result.body.size == 2 && !memcmp(result.body.data, "Hi", 2));
+ CHECK(pure_runtime_release(ticket));
+
+ const unsigned char append[] = {2,0,0,0, 0,0,0,0, '!'};
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "document", 1,
+ sizeof(append), &ticket) == PURE_OK);
+ memcpy(pure_runtime_ingress(ticket, NULL), append, sizeof(append));
+ CHECK(pure_runtime_ready(ticket));
+ CHECK(pure_runtime_take(&runtime, &effect) == PURE_TAKE_EFFECT &&
+ effect.value.size == sizeof(append));
+ CHECK(pure_program_splice(&program, effect.value, &offset, &remove) &&
+ offset == 2 && remove == 0);
+ reply = (PureSpan){0};
+ status = store.write(store.context, &program, effect.key, effect.expected,
+ effect.value, &reply, &revision);
+ CHECK(pure_runtime_complete(effect.ticket, status, NULL, reply, revision));
+ CHECK(pure_runtime_result(ticket, &result) && result.status == PURE_OK &&
+ result.body.size == 1 && result.body.data[0] == '!');
+ CHECK(pure_runtime_release(ticket));
+ expect(directory, "document", "Hi!", 3);
+
+ ticket = submit(&runtime, "document", append, sizeof(append));
+ CHECK(pure_runtime_take(&runtime, &effect) == PURE_TAKE_EFFECT);
+ reply = (PureSpan){0};
+ status = store.write(store.context, &program, effect.key, effect.expected,
+ effect.value, &reply, &revision);
+ CHECK(pure_runtime_complete(effect.ticket, status, NULL, reply, revision));
+ CHECK(pure_runtime_result(ticket, &result) && result.status == PURE_CONFLICT &&
+ !result.body.size);
+ CHECK(pure_runtime_release(ticket));
+ expect(directory, "document", "Hi!", 3);
+
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_READ, "document", 0, 0,
+ &ticket) == PURE_OK);
+ CHECK(pure_runtime_take(&runtime, &effect) == PURE_TAKE_EFFECT);
+ PureResource mapping = {0};
+ status = store.read(store.context, &program, effect.key,
+ effect.available, &mapping, &revision);
+ CHECK(pure_runtime_complete(effect.ticket, status, &mapping,
+ (PureSpan){0}, revision));
+ CHECK(pure_runtime_result(ticket, &result) && result.status == PURE_OK &&
+ result.body.size == 3 && !memcmp(result.body.data, "Hi!", 3));
+ CHECK(pure_runtime_release(ticket));
+ CHECK(runtime.active == 0 && runtime.retained == 0 &&
+ runtime.commits == 2 && runtime.conflicts == 1 && runtime.gets == 1);
+}
+
+int main(void) {
+ char template[] = "/tmp/pure-async-effects-XXXXXX";
+ char *directory = mkdtemp(template);
+ CHECK(directory && pure_store_init(directory) == PURE_OK);
+ worker_and_forward(directory);
+ rejection_and_budget(directory);
+ authored_document(directory);
+ DIR *opened = opendir(directory);
+ CHECK(opened);
+ struct dirent *entry;
+ while ((entry = readdir(opened))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(unlinkat(dirfd(opened), entry->d_name, 0) == 0);
+ }
+ CHECK(!closedir(opened) && !rmdir(directory));
+ puts("{\"async_effects\":\"authored-document-worker-overlap-release-forward-budget-recovery\"}");
+}
diff --git a/prototypes/connections/test-fields.c b/prototypes/connections/test-fields.c
new file mode 100644
index 0000000..63dfc3e
--- /dev/null
+++ b/prototypes/connections/test-fields.c
@@ -0,0 +1,153 @@
+#include "program.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static const char layout[] = "layout Envelope { marker: bytes[1]; start: u32le; count: u32le; text: bytes; }";
+static PureProgram parse(const char *source) {
+ PureProgram p;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &p, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return p;
+}
+static void invalid(const char *source) {
+ PureProgram p;
+ memset(&p, 0x5a, sizeof(p));
+ unsigned char before[sizeof(p)];
+ memcpy(before, &p, sizeof(p));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(*error && !memcmp(before, &p, sizeof(p)));
+}
+static void encode(unsigned char *at, uint32_t value) {
+ for (unsigned i = 0; i < 4; ++i) at[i] = (unsigned char)(value >> (8 * i));
+}
+int main(void) {
+ char source[8000];
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let alias = input; let start = alias.start; let text = alias.text; "
+ "let selected = range(text, start, alias.count); let result = selected; "
+ "let saved = store.write(request.key, request.revision, result); reply(saved, selected); }", layout, get);
+ PureProgram p = parse(source);
+ CHECK(p.input_steps == 1 && p.input_required == 9 && p.write_step == 1 && p.reply_step == 1);
+ CHECK(p.steps[0].source.offset == 9 && p.steps[0].source.to_end);
+ CHECK(p.steps[0].offset.value == 1 && p.steps[0].offset.from_u32le);
+ CHECK(p.steps[0].length.value == 5 && p.steps[0].length.from_u32le);
+ unsigned char bytes[609];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 13);
+ PureSpan stored, returned;
+ for (size_t n = 0; n < 9; ++n) {
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, n}, &stored, &returned));
+ CHECK(!stored.size && !returned.size);
+ }
+ const uint32_t offsets[] = {0, 1, 255, 257, 599, 600, 601, UINT32_MAX};
+ const uint32_t counts[] = {0, 1, 2, 260, 600, UINT32_MAX};
+ size_t comparisons = 0;
+ for (size_t i = 0; i < sizeof(offsets) / sizeof(*offsets); ++i)
+ for (size_t j = 0; j < sizeof(counts) / sizeof(*counts); ++j) {
+ uint32_t start = offsets[i], count = counts[j];
+ encode(bytes + 1, start);
+ encode(bytes + 5, count);
+ bool expected = start <= 600 && count <= 600 - start;
+ CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned) == expected);
+ if (expected) {
+ CHECK(stored.size == count && returned.size == count && stored.data == returned.data);
+ CHECK(!count || stored.data == bytes + 9 + start);
+ } else CHECK(!stored.size && !returned.size);
+ ++comparisons;
+ }
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let first = range(input.text, input.start, input.count); let second = range(first, 1, 2); "
+ "let saved = store.write(request.key, request.revision, second); reply(saved, second); }", layout, get);
+ p = parse(source);
+ CHECK(p.input_steps == 2 && p.steps[1].source_step == 1);
+ encode(bytes + 1, 3); encode(bytes + 5, 4);
+ CHECK(pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+ CHECK(stored.size == 2 && stored.data == bytes + 13);
+ encode(bytes + 5, 2);
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let unused = range(input.text, input.start, input.count); "
+ "let saved = store.write(request.key, request.revision, input.text); reply(saved); }", layout, get);
+ p = parse(source);
+ encode(bytes + 1, UINT32_MAX);
+ CHECK(!pure_program_input(&p, (PureSpan){bytes, sizeof(bytes)}, &stored, &returned));
+
+ snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); "
+ "let input = view(Envelope, o.body); reply(o, input.text); } %s", layout, put);
+ p = parse(source);
+ CHECK(p.read.to_end && p.read.offset == 9 && p.read_required == 9 && !p.input_steps);
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let selection = range(input.text, 2, 3); let saved = store.write(request.key, request.revision, selection); reply(saved); }", layout, get);
+ p = parse(source);
+ CHECK(!p.input_steps && p.write.offset == 11 && p.write.length == 3 && p.input_required == 14);
+ snprintf(source, sizeof(source), "layout Empty { body: bytes; } %s on put { let input = view(Empty, request.body); "
+ "let saved = store.write(request.key, request.revision, input.body); reply(saved, input.body); }", get);
+ p = parse(source);
+ CHECK(pure_program_input(&p, (PureSpan){0}, &stored, &returned) && !stored.size && !returned.size);
+
+ const char *bad_layout[] = {
+ "layout E {}", "layout E { x: bytes; y: u32le; }", "layout E { x: u32le; x: bytes; }",
+ "layout E { x: bytes[1449985]; }", "layout E { x: bytes[1449984]; y: u32le; }",
+ "layout E { x: bytes[184467440737095516160]; }", "layout E { x: u64le; }",
+ "layout E { x: u32le; } layout E { y: bytes; }"
+ };
+ for (size_t i = 0; i < sizeof(bad_layout) / sizeof(*bad_layout); ++i) {
+ snprintf(source, sizeof(source), "%s %s %s", bad_layout[i], get, put); invalid(source);
+ }
+ const char *bad_input[] = {
+ "let input = view(Missing, request.body);",
+ "let input = view(Envelope, request.body); let x = input.missing;",
+ "let input = view(Envelope, request.body); let x = range(input.text, input.text, 1);",
+ "let short = range(request.body, 0, 8); let input = view(Envelope, short);",
+ "let input = view(Envelope, request.body); let x = range(input.text, input.start, 20); let y = view(Envelope, x);"
+ };
+ for (size_t i = 0; i < sizeof(bad_input) / sizeof(*bad_input); ++i) {
+ snprintf(source, sizeof(source), "%s %s on put { %s let saved = store.write(request.key, request.revision, request.body); reply(saved); }", layout, get, bad_input[i]);
+ invalid(source);
+ }
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); "
+ "let saved = store.write(request.key, request.revision, input.start); reply(saved); }", layout, get);
+ invalid(source);
+ snprintf(source, sizeof(source), "%s on get { let o = store.read(request.key); let input = view(Envelope, o.body); "
+ "let x = range(input.text, input.start, input.count); reply(o, x); } %s", layout, put);
+ invalid(source);
+ for (size_t count = 8; count <= 9; ++count) {
+ snprintf(source, sizeof(source), "%s %s on put { let input = view(Envelope, request.body); ", layout, get);
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let v%zu = range(input.text, input.start, input.count); ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let saved = store.write(request.key, request.revision, input.text); reply(saved); }");
+ if (count == 8) CHECK(parse(source).input_steps == 8); else invalid(source);
+ }
+ for (size_t count = 4; count <= 5; ++count) {
+ source[0] = 0;
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "layout L%zu { body: bytes; } ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "%s %s", get, put);
+ if (count == 4) (void)parse(source); else invalid(source);
+ }
+ for (size_t count = 16; count <= 17; ++count) {
+ strcpy(source, "layout L { ");
+ for (size_t i = 0; i < count; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "f%zu: u32le; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "} %s %s", get, put);
+ if (count == 16) (void)parse(source); else invalid(source);
+ }
+ printf("{\"fields\":\"named-layouts-unaligned-u32le-tail-dynamic-ranges-aliases-failures-limits\","
+ "\"data_boundary_cases\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/test-flow.c b/prototypes/connections/test-flow.c
new file mode 100644
index 0000000..5ff028d
--- /dev/null
+++ b/prototypes/connections/test-flow.c
@@ -0,0 +1,183 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static int failed_stage = -1;
+static bool crash_at_stage;
+int pure_store_test_fault(PureStoreStage stage) {
+ if ((int)stage != failed_stage) return 0;
+ if (crash_at_stage) _exit(77);
+ return 1;
+}
+typedef struct { unsigned char *bytes; unsigned releases; } Owner;
+static void release(void *raw) {
+ Owner *owner = raw;
+ free(owner->bytes);
+ owner->bytes = NULL;
+ ++owner->releases;
+}
+
+static void transfers(void) {
+ Owner owner = {.bytes = malloc(5)};
+ CHECK(owner.bytes);
+ memcpy(owner.bytes, "a\0bcd", 5);
+ PureTransfer transfer = {0};
+ pure_transfer_init(&transfer, (PureSpan){(const unsigned char *)"head", 4},
+ (PureSpan){owner.bytes, 5}, &owner, release);
+ CHECK(!pure_transfer_consume(&transfer, 5));
+ CHECK(transfer.active && !owner.releases);
+ CHECK(pure_transfer_consume(&transfer, 0));
+ unsigned char received[9];
+ size_t used = 0;
+ while (transfer.active) {
+ PureSpan span = pure_transfer_next(&transfer, 2);
+ CHECK(span.size && span.size <= 2);
+ memcpy(received + used, span.data, span.size);
+ used += span.size;
+ CHECK(pure_transfer_consume(&transfer, span.size));
+ CHECK((used == 9) == (owner.releases == 1));
+ }
+ CHECK(used == 9 && !memcmp(received, "heada\0bcd", 9));
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 1 && !pure_transfer_consume(&transfer, 0));
+ owner.bytes = malloc(3);
+ CHECK(owner.bytes);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){owner.bytes, 3}, &owner, release);
+ CHECK(pure_transfer_consume(&transfer, 1));
+ pure_transfer_abort(&transfer);
+ pure_transfer_abort(&transfer);
+ CHECK(owner.releases == 2 && !transfer.active);
+ pure_transfer_init(&transfer, (PureSpan){0}, (PureSpan){0}, &owner, release);
+ CHECK(owner.releases == 3 && !transfer.active);
+}
+
+static void storage(const char *path) {
+ CHECK(pure_store_init(path) == PURE_OK);
+ PureStoredView first, second;
+ CHECK(pure_store_get(path, "missing", 100, &first) == PURE_NOT_FOUND);
+ CHECK(!first.mapping && !first.mapped_size);
+ static const unsigned char original[] = {0, 1, 2, 255, 17};
+ static const unsigned char updated[] = {9, 8, 7};
+ int64_t revision;
+ CHECK(pure_store_put(path, "work", 0, (PureSpan){original, sizeof(original)}, &revision) == PURE_OK);
+ CHECK(revision == 1);
+ CHECK(pure_store_get(path, "work", sizeof(original) - 1, &first) == PURE_BUDGET);
+ CHECK(!first.mapping && !first.mapped_size);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 3, &first) == PURE_OK);
+ CHECK(first.object_size == sizeof(original) && first.body.size == 3 && !memcmp(first.body.data, original + 1, 3));
+ pure_store_release(&first);
+ CHECK(pure_store_get_range(path, "work", SIZE_MAX, 1, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, SIZE_MAX, 10, &first) == PURE_LIMIT);
+ CHECK(pure_store_get_range(path, "work", 1, 3, 2, &first) == PURE_BUDGET);
+ CHECK(pure_store_get_range(path, "work", sizeof(original), 0, 0, &first) == PURE_OK);
+ CHECK(!first.mapped_size && !first.body.size);
+ pure_store_release(&first);
+ CHECK(pure_store_get(path, "work", sizeof(original), &first) == PURE_OK);
+ CHECK(first.body.size == sizeof(original) && first.revision == 1);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 2);
+ CHECK(!memcmp(first.body.data, original, sizeof(original)));
+ CHECK(pure_store_get(path, "work", 100, &second) == PURE_OK);
+ CHECK(second.revision == 2 && second.body.size == sizeof(updated));
+ CHECK(!memcmp(second.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ pure_store_release(&first);
+ pure_store_release(&second);
+ CHECK(pure_store_put(path, "work", 1, (PureSpan){original, sizeof(original)}, &revision) == PURE_CONFLICT);
+ CHECK(revision == 2);
+
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 2 && !memcmp(first.body.data, updated, sizeof(updated)));
+ pure_store_release(&first);
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){original, sizeof(original)}, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == 3);
+ failed_stage = -1;
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 2, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_CONFLICT);
+
+ /* A crashed unpublished writer leaves only a private file. A new publisher
+ * must still use the previous committed version, never an incomplete body. */
+ pid_t child = fork();
+ CHECK(child >= 0);
+ if (!child) {
+ failed_stage = PURE_AFTER_HEADER;
+ crash_at_stage = true;
+ pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision);
+ _exit(78);
+ }
+ int status;
+ CHECK(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 77);
+ CHECK(pure_store_init(path) == PURE_OK);
+ CHECK(pure_store_get(path, "work", 100, &first) == PURE_OK);
+ CHECK(first.revision == 3 && !memcmp(first.body.data, original, sizeof(original)));
+ pure_store_release(&first);
+ CHECK(pure_store_put(path, "work", 3, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_OK);
+ CHECK(revision == 4);
+
+ char file[320];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ CHECK(fd >= 0);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_put(path, "work", INT64_MAX, (PureSpan){original, sizeof(original)}, &revision) == PURE_LIMIT);
+ CHECK(pure_store_put(path, "empty", 0, (PureSpan){0}, &revision) == PURE_OK);
+ CHECK(pure_store_get(path, "empty", 0, &first) == PURE_OK && first.body.size == 0);
+ pure_store_release(&first);
+
+ /* Range mapping crosses page boundaries without copying a whole object. */
+ long page = sysconf(_SC_PAGESIZE);
+ CHECK(page >= 128 && (size_t)page <= PURE_OBJECT_LIMIT / 3);
+ size_t size = (size_t)page * 3, offset = (size_t)page + 13, length = (size_t)page + 105;
+ unsigned char *bytes = malloc(size);
+ CHECK(bytes);
+ for (size_t i = 0; i < size; ++i) bytes[i] = (unsigned char)((i * 17u) ^ (i >> 8) ^ (i >> 16));
+ CHECK(pure_store_put(path, "range", 0, (PureSpan){bytes, size}, &revision) == PURE_OK);
+ CHECK(pure_store_get_range(path, "range", offset, length, length, &first) == PURE_OK);
+ CHECK(first.body.size == length && !memcmp(first.body.data, bytes + offset, length));
+ pure_store_release(&first);
+ free(bytes);
+ snprintf(file, sizeof(file), "%s/obj-broken", path);
+ fd = open(file, O_CREAT | O_WRONLY | O_EXCL, 0600);
+ CHECK(fd >= 0 && write(fd, "incomplete", 10) == 10 && close(fd) == 0);
+ CHECK(pure_store_get(path, "broken", 100, &first) == PURE_STORE_ERROR && !first.mapped_size);
+ CHECK(pure_store_put(path, "broken", 0, (PureSpan){updated, sizeof(updated)}, &revision) == PURE_STORE_ERROR);
+ CHECK(pure_store_init(file) == PURE_STORE_ERROR);
+ struct stat info;
+ CHECK(stat(file, &info) == 0 && info.st_size == 10);
+}
+
+int main(void) {
+ transfers();
+ char directory[] = "/tmp/pure-connection-unit-XXXXXX";
+ CHECK(mkdtemp(directory));
+ char path[256];
+ snprintf(path, sizeof(path), "%s/store", directory);
+ storage(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ CHECK(rmdir(directory) == 0);
+ puts("{\"transfer\":\"partial-consumption-and-single-release\","
+ "\"storage\":\"mapped-ranges-snapshot-budget-conflict-failure-uncertain-crash-overflow-empty\"}");
+ return 0;
+}
diff --git a/prototypes/connections/test-paged-store.c b/prototypes/connections/test-paged-store.c
new file mode 100644
index 0000000..aed0539
--- /dev/null
+++ b/prototypes/connections/test-paged-store.c
@@ -0,0 +1,270 @@
+#define _POSIX_C_SOURCE 200809L
+#include "store.h"
+#include <assert.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+enum { PAGE = 16384, SIZE = 3 * PAGE + 23 };
+static int fail_stage = -1;
+static int crash;
+int pure_store_test_fault(PureStoreStage stage) {
+ if ((int)stage != fail_stage) return 0;
+ if (crash) _exit(77);
+ return 1;
+}
+
+static void expect(const char *path, int64_t revision, const unsigned char *bytes) {
+ PureStoredView view;
+ assert(pure_store_get(path, "large", SIZE, &view) == PURE_OK);
+ assert(view.revision == revision && view.body.size == SIZE &&
+ !memcmp(view.body.data, bytes, SIZE));
+ pure_store_release(&view);
+}
+
+static uint32_t random_value(uint32_t *state) {
+ *state ^= *state << 13;
+ *state ^= *state >> 17;
+ *state ^= *state << 5;
+ return *state;
+}
+
+static void expect_root(const char *path, const char *key,
+ const char magic[8], off_t size) {
+ char filename[320];
+ snprintf(filename, sizeof(filename), "%s/obj-%s", path, key);
+ struct stat info;
+ assert(stat(filename, &info) == 0 && info.st_size == size);
+ int fd = open(filename, O_RDONLY);
+ assert(fd >= 0);
+ char actual[8];
+ assert(read(fd, actual, sizeof(actual)) == sizeof(actual));
+ assert(!memcmp(actual, magic, sizeof(actual)));
+ assert(close(fd) == 0);
+}
+
+static void format_transitions(const char *path) {
+ unsigned char bytes[PAGE + 1];
+ memset(bytes, 'A', sizeof(bytes));
+ int64_t revision;
+ assert(pure_store_put(path, "boundary", 0, (PureSpan){bytes, PAGE},
+ &revision) == PURE_OK);
+ expect_root(path, "boundary", "PUREB001", 24 + PAGE);
+ PureStoredView old;
+ assert(pure_store_get(path, "boundary", PAGE + 1, &old) == PURE_OK);
+ assert(pure_store_splice(path, "boundary", revision, PAGE, 0,
+ (PureSpan){bytes, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ expect_root(path, "boundary", "PUREP001", 48 + 2 * 8);
+ assert(old.body.size == PAGE && old.body.data[PAGE - 1] == 'A');
+ pure_store_release(&old);
+ PureStoredView large;
+ assert(pure_store_get(path, "boundary", PAGE + 1, &large) == PURE_OK);
+ assert(large.body.size == PAGE + 1 && large.body.data[PAGE] == 'A');
+ assert(pure_store_splice(path, "boundary", revision, PAGE, 1,
+ (PureSpan){NULL, 0}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ expect_root(path, "boundary", "PUREB001", 24 + PAGE);
+ assert(large.body.size == PAGE + 1 && large.body.data[PAGE] == 'A');
+ pure_store_release(&large);
+ PureStoredView current;
+ assert(pure_store_get(path, "boundary", PAGE, &current) == PURE_OK);
+ assert(current.revision == 3 && current.body.size == PAGE &&
+ !memcmp(current.body.data, bytes, PAGE));
+ pure_store_release(&current);
+
+ const unsigned char one = 'X', two = 'Y';
+ assert(pure_store_put(path, "tiny", 0, (PureSpan){&one, 1}, &revision) == PURE_OK);
+ expect_root(path, "tiny", "PUREB001", 25);
+ assert(pure_store_splice(path, "tiny", revision, 1, 0,
+ (PureSpan){&two, 1}, 1, &revision) == PURE_LIMIT);
+ assert(revision == 1);
+ PureStoredView policy_view;
+ assert(pure_store_get(path, "tiny", 1, &policy_view) == PURE_OK);
+ assert(policy_view.revision == 1 && policy_view.body.size == 1 && policy_view.body.data[0] == one);
+ pure_store_release(&policy_view);
+ fail_stage = PURE_BEFORE_RENAME;
+ assert(pure_store_splice(path, "tiny", revision, 0, 1,
+ (PureSpan){&two, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_STORE_ERROR);
+ fail_stage = -1;
+ assert(pure_store_get(path, "tiny", 1, &current) == PURE_OK);
+ assert(current.revision == 1 && current.body.data[0] == one);
+ pure_store_release(&current);
+ fail_stage = PURE_BEFORE_DIR_SYNC;
+ assert(pure_store_splice(path, "tiny", revision, 0, 1,
+ (PureSpan){&two, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_UNCERTAIN);
+ fail_stage = -1;
+ assert(pure_store_get(path, "tiny", 1, &current) == PURE_OK);
+ assert(current.revision == 2 && current.body.data[0] == two);
+ pure_store_release(&current);
+
+ /* An existing flat-store object has no data segment. Its first large
+ * edit must read the old inline body before publishing a page root. */
+ char legacy_file[320];
+ snprintf(legacy_file, sizeof(legacy_file), "%s/obj-legacy", path);
+ int fd = open(legacy_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ assert(fd >= 0);
+ unsigned char header[24] = "PUREB001";
+ header[8] = 1;
+ header[16] = 1;
+ header[17] = 0x40; /* 0x4001 = 16 KiB + 1 */
+ assert(write(fd, header, sizeof(header)) == sizeof(header));
+ assert(write(fd, bytes, sizeof(bytes)) == sizeof(bytes));
+ assert(close(fd) == 0);
+ assert(pure_store_get(path, "legacy", PAGE + 1, &current) == PURE_OK);
+ assert(current.revision == 1 && current.body.size == PAGE + 1);
+ pure_store_release(&current);
+ assert(pure_store_splice(path, "legacy", 1, PAGE, 1,
+ (PureSpan){&two, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ expect_root(path, "legacy", "PUREP001", 48 + 2 * 8);
+ assert(pure_store_get(path, "legacy", PAGE + 1, &current) == PURE_OK);
+ assert(current.revision == 2 && current.body.size == PAGE + 1 &&
+ current.body.data[PAGE] == two);
+ pure_store_release(&current);
+}
+
+static void mixed_edits(const char *path) {
+ enum { CAPACITY = 6 * PAGE };
+ unsigned char *oracle = malloc(CAPACITY), *before = malloc(CAPACITY);
+ unsigned char insert[4096];
+ assert(oracle && before);
+ size_t length = 2 * PAGE + 17;
+ uint32_t state = 0xA17E532Du;
+ for (size_t i = 0; i < length; ++i) oracle[i] = (unsigned char)random_value(&state);
+ int64_t revision;
+ assert(pure_store_put(path, "mixed", 0, (PureSpan){oracle, length}, &revision) == PURE_OK);
+ for (unsigned step = 0; step < 128; ++step) {
+ size_t offset = random_value(&state) % (length + 1);
+ size_t remove = random_value(&state) % 4097;
+ if (remove > length - offset) remove = length - offset;
+ size_t count = step % 3 ? random_value(&state) % 4097 : remove;
+ if (count > CAPACITY - (length - remove)) count = CAPACITY - (length - remove);
+ for (size_t i = 0; i < count; ++i) insert[i] = (unsigned char)random_value(&state);
+ PureStoredView old;
+ assert(pure_store_get(path, "mixed", CAPACITY, &old) == PURE_OK);
+ if (length) memcpy(before, old.body.data, length);
+ assert(pure_store_splice(path, "mixed", revision, offset, remove,
+ (PureSpan){insert, count}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ assert(old.body.size == length &&
+ (!length || !memcmp(old.body.data, before, length)));
+ pure_store_release(&old);
+ memmove(oracle + offset + count, oracle + offset + remove, length - offset - remove);
+ memcpy(oracle + offset, insert, count);
+ length = length - remove + count;
+ PureStoredView current;
+ assert(pure_store_get(path, "mixed", CAPACITY, &current) == PURE_OK);
+ assert(current.revision == (int64_t)step + 2 && current.body.size == length &&
+ (!length || !memcmp(current.body.data, oracle, length)));
+ pure_store_release(&current);
+ }
+ free(before);
+ free(oracle);
+}
+
+int main(void) {
+ assert(sysconf(_SC_PAGESIZE) == PAGE);
+ char base[] = "/tmp/pure-page-store-XXXXXX";
+ assert(mkdtemp(base));
+ char path[256];
+ snprintf(path, sizeof(path), "%s/store", base);
+ assert(pure_store_init(path) == PURE_OK);
+ unsigned char expected[SIZE];
+ for (size_t i = 0; i < SIZE; ++i) expected[i] = (unsigned char)(i * 17u + i / PAGE);
+ int64_t revision;
+ assert(pure_store_put(path, "large", 0, (PureSpan){expected, SIZE}, &revision) == PURE_OK);
+ assert(revision == 1);
+ PureStoredView old;
+ assert(pure_store_get(path, "large", SIZE, &old) == PURE_OK);
+ unsigned char original = old.body.data[PAGE - 1];
+ const unsigned char replacement = 0xC7;
+ assert(pure_store_splice(path, "large", revision, PAGE - 1, 1,
+ (PureSpan){&replacement, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ expected[PAGE - 1] = replacement;
+ assert(revision == 2 && old.body.data[PAGE - 1] == original);
+ expect(path, revision, expected);
+ PureStoredView range;
+ assert(pure_store_get_range(path, "large", PAGE - 3, 9, 9, &range) == PURE_OK);
+ assert(!memcmp(range.body.data, expected + PAGE - 3, 9));
+ pure_store_release(&range);
+ char file[320];
+ struct stat info;
+ snprintf(file, sizeof(file), "%s/dat-large-%016x", path, 1);
+ assert(stat(file, &info) == 0 && info.st_size == (off_t)(5 * PAGE));
+
+ /* The bounded append log compacts into a new generation. The old view
+ * remains valid even after the old generation has been unlinked. */
+ for (unsigned i = 0; i < 3; ++i) {
+ unsigned char value = (unsigned char)(0xA0 + i);
+ assert(pure_store_splice(path, "large", revision, SIZE - 1, 1,
+ (PureSpan){&value, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ expected[SIZE - 1] = value;
+ expect(path, revision, expected);
+ }
+ assert(access(file, F_OK) != 0 && old.body.data[PAGE - 1] == original);
+ pure_store_release(&old);
+
+ /* Unpublished crashes may leave an orphan generation. They never change
+ * the visible root; the next writer must skip the collided generation. */
+ pid_t child = fork();
+ assert(child >= 0);
+ if (!child) {
+ fail_stage = PURE_BEFORE_RENAME;
+ crash = 1;
+ pure_store_put(path, "large", revision, (PureSpan){expected, SIZE}, &revision);
+ _exit(78);
+ }
+ int status;
+ assert(waitpid(child, &status, 0) == child && WIFEXITED(status) && WEXITSTATUS(status) == 77);
+ assert(pure_store_init(path) == PURE_OK);
+ expect(path, revision, expected);
+ unsigned char value = 0x5A;
+ assert(pure_store_splice(path, "large", revision, 0, 1,
+ (PureSpan){&value, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ expected[0] = value;
+ expect(path, revision, expected);
+
+ fail_stage = PURE_BEFORE_DIR_SYNC;
+ value = 0x36;
+ assert(pure_store_splice(path, "large", revision, PAGE + 4, 1,
+ (PureSpan){&value, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_UNCERTAIN);
+ fail_stage = -1;
+ expected[PAGE + 4] = value;
+ expect(path, revision, expected);
+
+ /* A whole replacement must skip the generation orphaned by the crash. */
+ assert(pure_store_put(path, "large", revision,
+ (PureSpan){expected, SIZE}, &revision) == PURE_OK);
+ expect(path, revision, expected);
+ DIR *segments = opendir(path);
+ assert(segments);
+ unsigned generations = 0;
+ struct dirent *segment;
+ while ((segment = readdir(segments))) {
+ assert(strncmp(segment->d_name, ".pending-", 9));
+ if (!strncmp(segment->d_name, "dat-large-", 10)) ++generations;
+ }
+ assert(closedir(segments) == 0 && generations == 1);
+ const unsigned char initial[] = "abcde", inserted[] = "XYZ";
+ assert(pure_store_put(path, "variable", 0,
+ (PureSpan){initial, 5}, &revision) == PURE_OK);
+ assert(pure_store_splice(path, "variable", revision, 1, 2,
+ (PureSpan){inserted, 3}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ PureStoredView variable;
+ assert(pure_store_get(path, "variable", 6, &variable) == PURE_OK);
+ assert(variable.body.size == 6 && !memcmp(variable.body.data, "aXYZde", 6));
+ pure_store_release(&variable);
+ format_transitions(path);
+ mixed_edits(path);
+ DIR *directory = opendir(path);
+ assert(directory);
+ struct dirent *entry;
+ while ((entry = readdir(directory))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ assert(unlinkat(dirfd(directory), entry->d_name, 0) == 0);
+ }
+ assert(closedir(directory) == 0 && rmdir(path) == 0 && rmdir(base) == 0);
+ puts("{\"hybrid_storage\":\"snapshot-patch-range-compaction-crash-conflict-uncertain-inline-transitions\",\"mixed_edits\":128}");
+}
diff --git a/prototypes/connections/test-program.c b/prototypes/connections/test-program.c
new file mode 100644
index 0000000..6a4a19d
--- /dev/null
+++ b/prototypes/connections/test-program.c
@@ -0,0 +1,111 @@
+#include "program.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define CHECK(expr) do { if (!(expr)) { fprintf(stderr, "line %d: %s\n", __LINE__, #expr); exit(1); } } while (0)
+static const char get[] = "on get { let o = store.read(request.key); reply(o, o.body); }";
+static const char put[] = "on put { let s = store.write(request.key, request.revision, request.body); reply(s); }";
+static PureProgram parse(const char *source) {
+ PureProgram program;
+ char error[160];
+ if (!pure_program_parse(source, strlen(source), &program, error, sizeof(error))) {
+ fprintf(stderr, "%s\n", error); exit(1);
+ }
+ return program;
+}
+static void invalid(const char *source) {
+ PureProgram program;
+ memset(&program, 0x5a, sizeof(program));
+ unsigned char original[sizeof(program)];
+ memcpy(original, &program, sizeof(program));
+ char error[160];
+ CHECK(!pure_program_parse(source, strlen(source), &program, error, sizeof(error)));
+ CHECK(*error && !memcmp(original, &program, sizeof(program)));
+}
+int main(void) {
+ char source[4096];
+ snprintf(source, sizeof(source), "%s %s", get, put);
+ PureProgram plan = parse(source);
+ CHECK(plan.read.to_end && plan.write.to_end && !plan.reply_input);
+ CHECK(!plan.view_definitions && !plan.read_required && !plan.input_required);
+ snprintf(source, sizeof(source), "%s on put { let a = range(request.body, 2, 10); "
+ "let b = range(a, 3, 4); let alias = b; "
+ "let saved = store.write(request.key, request.revision, alias); reply(saved, b); }", get);
+ plan = parse(source);
+ CHECK(plan.write.offset == 5 && plan.write.length == 4 && !plan.write.to_end);
+ CHECK(plan.reply.offset == 5 && plan.reply.length == 4 && plan.reply_input);
+ CHECK(plan.input_required == 12 && plan.range_definitions == 2 && plan.view_definitions == 3);
+ /* Ordered reference views keep even unused bounds failures observable. */
+ unsigned char bytes[160];
+ for (size_t i = 0; i < sizeof(bytes); ++i) bytes[i] = (unsigned char)(i * 7);
+ size_t comparisons = 0;
+ for (size_t a = 0; a < 4; ++a) for (size_t b = 0; b < 6; ++b)
+ for (size_t c = 0; c <= b; ++c) for (size_t d = 0; d <= b - c; ++d) {
+ size_t unused_end = (a + b + c) % 12;
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); "
+ "let unused = range(o.body, %zu, 0); let first = range(o.body, %zu, %zu); "
+ "let second = range(first, %zu, %zu); reply(o, second); } %s",
+ unused_end, a, b, c, d, put);
+ plan = parse(source);
+ for (size_t n = 0; n < 16; ++n) {
+ bool reference_ok = unused_end <= n && a <= n && b <= n - a;
+ PureSpan selected;
+ bool prepared_ok = n >= plan.read_required &&
+ pure_region_span(plan.read, (PureSpan){bytes, n}, &selected);
+ CHECK(reference_ok == prepared_ok);
+ if (reference_ok) {
+ CHECK(selected.size == d);
+ CHECK(!d || !memcmp(selected.data, bytes + a + c, d));
+ }
+ ++comparisons;
+ }
+ }
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); reply(o); } %s", put);
+ plan = parse(source);
+ CHECK(!plan.read.to_end && !plan.read.length);
+ const char *bad_get[] = {
+ "on get { let o = store.read(request.key); let x = range(o.body, 0, 2); let y = range(x, 2, 1); reply(o, y); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 184467440737095516160, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = range(o.body, 1449984, 1); reply(o, x); }",
+ "on get { let o = store.read(request.key); let o = o.body; reply(o); }",
+ "on get { let o = store.read(request.key); let x = x; reply(o, x); }",
+ "on get { let o = store.read(request.key); let x = store.read(request.key); reply(x); }",
+ "on get { let o = store.read(request.key); reply(o, request.body); }",
+ "on get { let o = store.read(request.key); let x = o.body; reply(x); }",
+ "on get { let o = store.read(request.key); reply(o.body); }",
+ "on get { let o = store.read(request.key); reply(o); let x = o.body; }",
+ "on get { let o = store.read(request.key); reply(o);", "on get {}"
+ };
+ for (size_t i = 0; i < sizeof(bad_get) / sizeof(*bad_get); ++i) {
+ snprintf(source, sizeof(source), "%s %s", bad_get[i], put); invalid(source);
+ }
+ const char *bad_put[] = {
+ "on put { let s = store.write(request.key, request.revision, request.body); let b = range(request.body, 0, 1); reply(s, b); }",
+ "on put { let s = store.write(request.key, request.revision, request.body); reply(s, s.body); }",
+ "on put { let s = store.read(request.key); reply(s); }"
+ };
+ for (size_t i = 0; i < sizeof(bad_put) / sizeof(*bad_put); ++i) {
+ snprintf(source, sizeof(source), "%s %s", get, bad_put[i]); invalid(source);
+ }
+ invalid(get);
+ snprintf(source, sizeof(source), "%s %s %s", get, get, put); invalid(source);
+ snprintf(source, sizeof(source), "%s %s garbage", get, put); invalid(source);
+ snprintf(source, sizeof(source), "on get { let o = store.read(request.key); ");
+ for (size_t i = 0; i < 32; ++i) {
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "let x%zu = o.body; ", i);
+ }
+ size_t used = strlen(source);
+ snprintf(source + used, sizeof(source) - used, "reply(o); } %s", put); invalid(source);
+ char oversized[PURE_PROGRAM_LIMIT + 1];
+ memset(oversized, ' ', sizeof(oversized));
+ char error[160];
+ CHECK(!pure_program_parse(oversized, sizeof(oversized), &plan, error, sizeof(error)));
+ const char embedded[] = "on get\0{}";
+ CHECK(!pure_program_parse(embedded, sizeof(embedded) - 1, &plan, error, sizeof(error)));
+ PureSpan selected;
+ CHECK(pure_region_span((PureRegion){0}, (PureSpan){0}, &selected) && !selected.data && !selected.size);
+ printf("{\"program\":\"prepare-views-preserve-guards-types-effects-and-atomic-install\","
+ "\"boundary_semantic_comparisons\":%zu}\n", comparisons);
+ return 0;
+}
diff --git a/prototypes/connections/test-runtime.c b/prototypes/connections/test-runtime.c
new file mode 100644
index 0000000..0883ec8
--- /dev/null
+++ b/prototypes/connections/test-runtime.c
@@ -0,0 +1,356 @@
+#define _POSIX_C_SOURCE 200809L
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <assert.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const PureProgram identity = {
+ .read = {.to_end = true}, .write = {.to_end = true},
+ .reply = {.to_end = true}, .reply_input = true
+};
+
+static void remove_store(const char *path) {
+ DIR *directory = opendir(path);
+ assert(directory);
+ struct dirent *entry;
+ while ((entry = readdir(directory))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ assert(unlinkat(dirfd(directory), entry->d_name, 0) == 0);
+ }
+ assert(closedir(directory) == 0 && rmdir(path) == 0);
+}
+typedef struct {
+ size_t allocations, writes, frees, live;
+ bool allocation_failure, invalid_allocation, oversized_read, foreign_reply, reenter, reenter_release;
+ PureRuntime *runtime;
+ PureTicket release_ticket;
+ unsigned char received[256];
+ size_t received_size;
+} Host;
+typedef struct { Host *host; unsigned char bytes[]; } Allocation;
+
+static void free_input(void *pointer, size_t size) {
+ Allocation *a = pointer;
+ assert(size > 0 && a->host->live > 0);
+ if (a->host->reenter_release) {
+ PureTicket ignored = {0};
+ assert(!pure_runtime_release(a->host->release_ticket));
+ assert(pure_runtime_accept(a->host->runtime, PURE_INPUT_WRITE,
+ "reenter", 0, 0, &ignored) == PURE_INVALID);
+ }
+ ++a->host->frees;
+ --a->host->live;
+ free(a);
+}
+
+static bool allocate(void *context, size_t size, PureResource *out) {
+ Host *host = context;
+ if (host->allocation_failure) return false;
+ Allocation *a = malloc(sizeof(*a) + size);
+ assert(a);
+ a->host = host;
+ ++host->allocations;
+ ++host->live;
+ *out = (PureResource){.body = {a->bytes, size + (host->invalid_allocation ? 1u : 0u)}, .allocation = a,
+ .allocation_size = size, .release = free_input};
+ return true;
+}
+
+static PureResult write_value(void *context, const void *definition, const char *key,
+ int64_t expected, PureSpan input, PureSpan *reply,
+ int64_t *revision) {
+ Host *host = context;
+ (void)key;
+ PureSpan body;
+ if (!pure_program_input(definition, input, &body, reply)) return PURE_LIMIT;
+ if (host->foreign_reply) {
+ *reply = (PureSpan){(const unsigned char *)"outside", 7};
+ *revision = 1;
+ return PURE_OK;
+ }
+ if (host->reenter) {
+ PureTicket ignored;
+ assert(pure_runtime_accept(host->runtime, PURE_INPUT_WRITE, "reenter", 0, 0, &ignored) == PURE_INVALID);
+ assert(!pure_runtime_step(host->runtime));
+ }
+ if (expected == 99) { *revision = 1; return PURE_CONFLICT; }
+ ++host->writes;
+ assert(body.size <= sizeof(host->received));
+ if (body.size) memcpy(host->received, body.data, body.size);
+ host->received_size = body.size;
+ *revision = 1;
+ return PURE_OK;
+}
+
+static PureResult read_value(void *context, const void *definition, const char *key,
+ size_t available, PureResource *out, int64_t *revision) {
+ Host *host = context;
+ (void)definition; (void)key;
+ if (!host->oversized_read) return PURE_NOT_FOUND;
+ assert(available < 1000);
+ assert(allocate(host, available + 1, out));
+ *revision = 1;
+ return PURE_OK; /* Deliberately violates the available-credit contract. */
+}
+
+static PureHost port(Host *host) {
+ return (PureHost){.context = host, .allocate = allocate, .read = read_value, .write = write_value};
+}
+
+static PureTicket submit(PureRuntime *r, const char *key, const void *bytes, size_t length) {
+ PureTicket ticket;
+ assert(pure_runtime_accept(r, PURE_INPUT_WRITE, key, 0, length, &ticket) == PURE_OK);
+ size_t capacity;
+ unsigned char *input = pure_runtime_ingress(ticket, &capacity);
+ assert(capacity == length);
+ if (length) memcpy(input, bytes, length);
+ assert(pure_runtime_ready(ticket));
+ assert(!pure_runtime_ready(ticket));
+ return ticket;
+}
+
+static PureOutcome completed(PureRuntime *r, PureTicket ticket) {
+ PureOutcome result;
+ while (!pure_runtime_result(ticket, &result)) assert(pure_runtime_step(r));
+ return result;
+}
+
+static void admission_and_lifecycle(void) {
+ Host host = {0};
+ PureRuntime r;
+ PureWork work[3];
+ assert(pure_runtime_init(&r, work, 3, &identity, port(&host), 5));
+ host.runtime = &r;
+ PureTicket a, untouched = {0}, out = untouched;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "../bad", 0, 1, &out) == PURE_INVALID);
+ assert(!out.runtime && !host.allocations);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "a", 0, 4, &a) == PURE_OK);
+ assert(r.retained == 4 && !pure_runtime_step(&r) && !host.writes);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "b", 0, 2, &out) == PURE_BUDGET);
+ assert(!out.runtime && host.allocations == 1);
+ host.reenter_release = true;
+ host.release_ticket = a;
+ assert(pure_runtime_cancel(a));
+ host.reenter_release = false;
+ PureOutcome cancelled;
+ assert(pure_runtime_result(a, &cancelled) && cancelled.status == PURE_CANCELLED);
+ assert(r.retained == 0 && host.frees == 1 && !pure_runtime_cancel(a));
+ assert(pure_runtime_release(a) && !pure_runtime_release(a));
+ assert(!pure_runtime_result(a, &cancelled));
+
+ PureTicket first = submit(&r, "first", "1", 1);
+ PureTicket middle = submit(&r, "middle", "2", 1);
+ PureTicket last = submit(&r, "last", "3", 1);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "full", 0, 0, &out) == PURE_BUSY);
+ assert(pure_runtime_cancel(middle));
+ assert(pure_runtime_release(middle));
+ pure_runtime_stop(&r);
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "closed", 0, 0, &out) == PURE_CLOSED);
+ assert(!pure_runtime_restart(&r, &identity, port(&host), 5));
+ host.reenter = true;
+ assert(completed(&r, first).status == PURE_OK && host.received[0] == '1');
+ assert(completed(&r, last).status == PURE_OK && host.received[0] == '3');
+ assert(!pure_runtime_step(&r));
+ assert(pure_runtime_release(first) && pure_runtime_release(last));
+ assert(r.active == 0 && r.retained == 0 && host.live == 0);
+ assert(pure_runtime_restart(&r, &identity, port(&host), 5));
+ PureTicket next = submit(&r, "next", "4", 1);
+ assert(next.generation > last.generation && !pure_runtime_ready(a));
+ assert(!pure_runtime_release(last));
+ host.reenter_release = true;
+ host.release_ticket = next;
+ assert(pure_runtime_release(next)); /* queued input: no effect */
+ host.reenter_release = false;
+ assert(host.writes == 2 && !pure_runtime_step(&r));
+
+ host.allocation_failure = true;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "no_memory", 0, 1, &out) == PURE_ALLOCATION);
+ assert(r.active == 0 && r.retained == 0);
+ host.allocation_failure = false;
+ host.invalid_allocation = host.reenter_release = true;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "bad_allocation", 0, 1, &out) == PURE_ALLOCATION);
+ assert(r.active == 0 && r.retained == 0 && host.live == 0);
+ host.invalid_allocation = host.reenter_release = false;
+ PureHost denied = port(&host);
+ denied.write = NULL;
+ assert(pure_runtime_restart(&r, &identity, denied, 5));
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "denied", 0, 1, &out) == PURE_DENIED);
+ assert(pure_runtime_restart(&r, &identity, port(&host), 5));
+ host.oversized_read = true;
+ assert(pure_runtime_accept(&r, PURE_INPUT_READ, "bad_host", 0, 0, &out) == PURE_OK);
+ assert(completed(&r, out).status == PURE_BUDGET && host.live == 0 && r.retained == 0);
+ assert(pure_runtime_release(out));
+ host.foreign_reply = true;
+ PureTicket invalid_reply = submit(&r, "bad_reply", "x", 1);
+ assert(completed(&r, invalid_reply).status == PURE_STORE_ERROR);
+ assert(r.retained == 0 && host.live == 0 && pure_runtime_release(invalid_reply));
+ host.foreign_reply = false;
+ r.serial = UINT64_MAX;
+ assert(pure_runtime_accept(&r, PURE_INPUT_WRITE, "exhausted", 0, 0, &out) == PURE_LIMIT);
+}
+
+static void forwarding(void) {
+ Host a = {0}, b = {0}, c = {0};
+ PureRuntime source, left, right;
+ PureWork source_work[1], left_work[1], right_work[1];
+ assert(pure_runtime_init(&source, source_work, 1, &identity, port(&a), 8));
+ assert(pure_runtime_init(&left, left_work, 1, &identity, port(&b), 2));
+ assert(pure_runtime_init(&right, right_work, 1, &identity, port(&c), 8));
+ PureTicket original = submit(&source, "original", "value", 5), x = {0}, y;
+ PureOutcome result = completed(&source, original);
+ assert(result.status == PURE_OK);
+ const unsigned char *backing = result.body.data;
+ assert(pure_runtime_forward(original, &left, "left", 0, &x) == PURE_BUDGET);
+ assert(!x.runtime && source.work[0].pins == 0);
+ assert(pure_runtime_restart(&left, &identity, port(&b), 8));
+ assert(pure_runtime_forward(original, &left, "left", 0, &x) == PURE_OK);
+ assert(pure_runtime_forward(original, &right, "right", 0, &y) == PURE_OK);
+ assert(pure_runtime_release(original));
+ assert(!pure_runtime_result(original, &result));
+ pure_runtime_stop(&source);
+ assert(!pure_runtime_restart(&source, &identity, port(&a), 8));
+ assert(a.live == 1 && !b.allocations && !c.allocations);
+ assert(pure_runtime_cancel(x) && pure_runtime_release(x));
+ assert(a.live == 1 && !b.writes);
+ result = completed(&right, y);
+ assert(result.body.data == backing && result.body.size == 5 && !memcmp(result.body.data, "value", 5));
+ assert(c.writes == 1 && !c.allocations && source.retained == 5);
+ assert(!pure_runtime_cancel(y)); /* effects cannot be rolled back */
+ assert(pure_runtime_release(y));
+ assert(a.frees == 1 && !source.active && !source.retained && !right.active && !right.retained);
+ assert(pure_runtime_restart(&source, &identity, port(&a), 8));
+
+ /* A completed consumer does not retain its input when the program has no
+ * input-backed reply. The producing domain can then be reclaimed early. */
+ PureProgram no_reply = identity;
+ no_reply.reply_input = false;
+ assert(pure_runtime_restart(&right, &no_reply, port(&c), 8));
+ original = submit(&source, "again", "last", 4);
+ assert(completed(&source, original).status == PURE_OK);
+ assert(pure_runtime_forward(original, &right, "no_reply", 0, &y) == PURE_OK);
+ assert(pure_runtime_release(original));
+ assert(completed(&right, y).body.size == 0 && a.live == 0);
+ assert(source.active == 0 && right.active == 1 && right.retained == 0);
+ assert(pure_runtime_release(y));
+}
+
+static void idle_binding(void) {
+ Host a = {0}, b = {0};
+ PureRuntime source, destination;
+ PureWork source_work[1], destination_work[1];
+ PureTicket first = {0};
+ assert(pure_runtime_init(&source, NULL, 0, &identity, port(&a), 8));
+ assert(pure_runtime_init(&destination, destination_work, 1, &identity, port(&b), 8));
+ assert(pure_runtime_accept(&source, PURE_INPUT_WRITE, "idle", 0, 1, &first) == PURE_BUSY);
+ assert(!first.runtime && !pure_runtime_bind(&source, NULL, 1));
+ assert(pure_runtime_bind(&source, source_work, 1));
+ first = submit(&source, "source", "abc", 3);
+ assert(!pure_runtime_bind(&source, NULL, 0));
+ assert(completed(&source, first).status == PURE_OK);
+ PureTicket receiver;
+ assert(pure_runtime_forward(first, &destination, "receiver", 0, &receiver) == PURE_OK);
+ assert(pure_runtime_release(first));
+ assert(!pure_runtime_bind(&source, NULL, 0)); /* The receiver still pins its backing. */
+ assert(completed(&destination, receiver).status == PURE_OK);
+ assert(pure_runtime_release(receiver));
+ assert(!source.active && !source.retained && !a.live);
+ assert(pure_runtime_bind(&source, NULL, 0));
+ assert(!pure_runtime_result(first, &(PureOutcome){0}));
+ assert(pure_runtime_bind(&source, source_work, 1));
+ PureTicket second = submit(&source, "again", "d", 1);
+ assert(second.generation > first.generation && !pure_runtime_ready(first));
+ assert(completed(&source, second).status == PURE_OK);
+ assert(pure_runtime_release(second));
+ assert(pure_runtime_bind(&source, NULL, 0));
+ assert(source.accepted == 2 && source.releases == 2 && source.serial == second.generation);
+}
+
+static void long_chain(void) {
+ enum { COUNT = 1024 };
+ PureWork *work = calloc(COUNT, sizeof(*work));
+ assert(work);
+ Host host = {0};
+ PureRuntime r;
+ assert(pure_runtime_init(&r, work, COUNT, &identity, port(&host), COUNT));
+ PureTicket ticket = submit(&r, "chain", "x", 1);
+ for (size_t i = 1; i < COUNT; ++i) {
+ assert(completed(&r, ticket).status == PURE_OK);
+ PureTicket next;
+ assert(pure_runtime_forward(ticket, &r, "chain", 0, &next) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ ticket = next;
+ }
+ assert(completed(&r, ticket).status == PURE_OK);
+ assert(host.allocations == 1 && r.active == COUNT);
+ assert(pure_runtime_release(ticket));
+ assert(r.retained == 0 && r.active == 0 && host.frees == 1);
+ free(work);
+}
+
+static void actual_storage(void) {
+ char directory[] = "/tmp/pure-runtime-check-XXXXXX";
+ assert(mkdtemp(directory));
+ char source_path[128], target_path[128];
+ snprintf(source_path, sizeof(source_path), "%s/source", directory);
+ snprintf(target_path, sizeof(target_path), "%s/target", directory);
+ assert(pure_store_init(source_path) == PURE_OK && pure_store_init(target_path) == PURE_OK);
+ PureProgram selection;
+ char error[160];
+ assert(pure_program_load("examples/selection.pure", &selection, error, sizeof(error)));
+ PureRuntime source, target;
+ PureWork a[2], b[2];
+ assert(pure_runtime_init(&source, a, 2, &selection, pure_store_host(source_path), 128));
+ assert(pure_runtime_init(&target, b, 2, &identity, pure_store_host(target_path), 128));
+ const unsigned char bytes[] = {1,0,0,0, 3,0,0,0, 'a','b','c','d','e'};
+ PureTicket ticket = submit(&source, "excerpt", bytes, sizeof(bytes)), consumer;
+ PureOutcome result = completed(&source, ticket);
+ assert(result.status == PURE_OK && result.body.size == 3 && !memcmp(result.body.data, "bcd", 3));
+ assert(pure_runtime_forward(ticket, &target, "archive", 0, &consumer) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ assert(source.active == 1 && source.retained == sizeof(bytes));
+ assert(completed(&target, consumer).status == PURE_OK);
+ assert(pure_runtime_release(consumer) && source.active == 0);
+ PureStoredView stored = {0};
+ assert(pure_store_get(target_path, "archive", 128, &stored) == PURE_OK);
+ assert(stored.body.size == 3 && !memcmp(stored.body.data, "bcd", 3));
+ pure_store_release(&stored);
+
+ assert(pure_runtime_accept(&source, PURE_INPUT_READ, "excerpt", 0, 0, &ticket) == PURE_OK);
+ assert(completed(&source, ticket).status == PURE_OK);
+ assert(pure_runtime_forward(ticket, &target, "snapshot", 0, &consumer) == PURE_OK);
+ assert(pure_runtime_release(ticket));
+ int64_t revision;
+ assert(pure_store_put(source_path, "excerpt", 1, (PureSpan){(const unsigned char *)"new", 3}, &revision) == PURE_OK);
+ result = completed(&target, consumer);
+ assert(result.body.size == 3 && !memcmp(result.body.data, "bcd", 3));
+ assert(pure_runtime_release(consumer));
+
+ unsigned char invalid[] = {255,255,255,255, 1,0,0,0, 'x'};
+ ticket = submit(&source, "invalid", invalid, sizeof(invalid));
+ assert(completed(&source, ticket).status == PURE_LIMIT);
+ assert(pure_runtime_release(ticket));
+ assert(pure_store_get(source_path, "invalid", 128, &stored) == PURE_NOT_FOUND);
+ assert(source.active == 0 && target.active == 0 && source.retained == 0 && target.retained == 0);
+ remove_store(source_path);
+ remove_store(target_path);
+ assert(rmdir(directory) == 0);
+}
+
+int main(void) {
+ admission_and_lifecycle();
+ forwarding();
+ idle_binding();
+ long_chain();
+ actual_storage();
+ printf("{\"runtime_tests\":\"passed\",\"domain_bytes\":%zu,\"work_slot_bytes\":%zu,"
+ "\"ticket_bytes\":%zu,\"prepared_program_bytes\":%zu,\"forwarding_chain\":1024,"
+ "\"native_storage_pipeline\":true,\"idle_slot_binding\":true,"
+ "\"release_reentrancy_guard\":true}\n", sizeof(PureRuntime), sizeof(PureWork),
+ sizeof(PureTicket), sizeof(PureProgram));
+ return 0;
+}
diff --git a/prototypes/connections/test-splice.c b/prototypes/connections/test-splice.c
new file mode 100644
index 0000000..bf3c0a9
--- /dev/null
+++ b/prototypes/connections/test-splice.c
@@ -0,0 +1,190 @@
+#define _POSIX_C_SOURCE 200809L
+#include "runtime.h"
+#include "store-port.h"
+#include "store.h"
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CHECK(x) do { if (!(x)) { fprintf(stderr, "line %d: %s\n", __LINE__, #x); exit(1); } } while (0)
+static int failed_stage = -1;
+int pure_store_test_fault(PureStoreStage stage) { return (int)stage == failed_stage; }
+
+static void expect(const char *path, const char *key, int64_t revision, PureSpan bytes) {
+ PureStoredView view;
+ CHECK(pure_store_get(path, key, PURE_OBJECT_LIMIT, &view) == PURE_OK);
+ CHECK(view.revision == revision && view.body.size == bytes.size);
+ CHECK(!bytes.size || !memcmp(view.body.data, bytes.data, bytes.size));
+ pure_store_release(&view);
+}
+
+static void parser(void) {
+ const char *get = "on get { let o = store.read(request.key); reply(o, o.body); }";
+ const char *layout = "layout E { marker: bytes[1]; remove: u32le; start: u32le; insert: bytes; }";
+ char source[2048], error[160];
+ PureProgram p;
+ snprintf(source, sizeof(source), "%s %s on put { let e = view(E, request.body); "
+ "let s = store.splice(request.key, request.revision, e.start, e.remove, e.insert); reply(s, e.insert); }", layout, get);
+ CHECK(pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(p.splice && p.input_required == 9 && p.splice_offset.value == 5 && p.splice_remove.value == 1);
+ CHECK(p.splice_limit == PURE_OBJECT_LIMIT);
+ unsigned char input[] = {0, 2,0,0,0, 3,0,0,0, 0,255};
+ PureSpan write, reply;
+ size_t offset, remove;
+ for (size_t n = 0; n < 9; ++n)
+ CHECK(!pure_program_input(&p, (PureSpan){input, n}, &write, &reply));
+ CHECK(pure_program_input(&p, (PureSpan){input, sizeof(input)}, &write, &reply));
+ CHECK(write.size == 2 && write.data == input + 9 && reply.data == write.data);
+ CHECK(pure_program_splice(&p, (PureSpan){input, sizeof(input)}, &offset, &remove));
+ CHECK(offset == 3 && remove == 2);
+
+ snprintf(source, sizeof(source), "%s on put { let s = store.splice(request.key, request.revision, 0, 0, request.body); reply(s); }", get);
+ CHECK(pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(pure_program_splice(&p, (PureSpan){0}, &offset, &remove) && offset == 0 && remove == 0);
+ snprintf(source, sizeof(source), "%s on put { let s = store.splice(request.key, request.revision, 0, 0, request.body, 8); reply(s); }", get);
+ CHECK(pure_program_parse(source, strlen(source), &p, error, sizeof(error)) && p.splice_limit == 8);
+ const char *invalid[] = {
+ "let s = store.splice(request.key, request.revision, e.insert, 0, e.insert); reply(s);",
+ "let s = store.splice(request.key, request.revision, 0, 1449985, e.insert); reply(s);",
+ "let s = store.splice(request.key, request.revision, 0, 0, e.start); reply(s);",
+ "let s = store.splice(request.key, request.revision, 0, 0, e.insert); let t = store.write(request.key, request.revision, e.insert); reply(t);",
+ "let s = store.splice(request.key, request.revision, 0, 0, e.insert, e.start); reply(s);",
+ "let s = store.splice(request.key, request.revision, 0, 0, e.insert, 1449985); reply(s);"
+ };
+ for (size_t i = 0; i < sizeof(invalid) / sizeof(*invalid); ++i) {
+ snprintf(source, sizeof(source), "%s %s on put { let e = view(E, request.body); %s }", layout, get, invalid[i]);
+ unsigned char before[sizeof(p)];
+ memcpy(before, &p, sizeof(p));
+ CHECK(!pure_program_parse(source, strlen(source), &p, error, sizeof(error)));
+ CHECK(*error && !memcmp(before, &p, sizeof(p)));
+ }
+}
+
+static void storage(const char *path) {
+ /* Reference whole-value assembly exists only in this test oracle. */
+ unsigned char oracle[65536], before[65536], insert[9000];
+ for (size_t i = 0; i < sizeof(insert); ++i) insert[i] = (unsigned char)(i * 19u);
+ size_t length = 49157;
+ for (size_t i = 0; i < length; ++i) oracle[i] = (unsigned char)((i * 17u) ^ (i >> 8));
+ int64_t revision;
+ CHECK(pure_store_splice(path, "work", 0, 0, 0, (PureSpan){oracle, length}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ CHECK(revision == 1);
+#if defined(PURE_STORE_CFR_COPY) && defined(__linux__)
+ /* A short kernel copy followed by an unsupported result must continue
+ * from exactly the remaining source and destination byte positions. */
+ unsigned char replacement = 'Z';
+ failed_stage = PURE_COPY_RANGE_UNSUPPORTED_AFTER_PARTIAL;
+ CHECK(pure_store_splice(path, "work", revision, 32768, 1,
+ (PureSpan){&replacement, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ failed_stage = -1;
+ oracle[32768] = replacement;
+ expect(path, "work", revision, (PureSpan){oracle, length});
+#endif
+ /* Prefix/suffix copies cross both scratch and mapping page boundaries. */
+ const size_t edits[][3] = {{16381, 7, 9000}, {0, 0, 5}, {50000, 1, 0}, {4095, 4097, 3}, {0, 0, 0}};
+ for (size_t i = 0; i < sizeof(edits) / sizeof(*edits); ++i) {
+ size_t offset = edits[i][0], remove = edits[i][1], count = edits[i][2], previous = length;
+ memcpy(before, oracle, length);
+ PureStoredView old;
+ CHECK(pure_store_get(path, "work", PURE_OBJECT_LIMIT, &old) == PURE_OK);
+ int64_t expected = revision;
+ CHECK(pure_store_splice(path, "work", expected, offset, remove, (PureSpan){insert, count}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ CHECK(revision == expected + 1);
+ memmove(oracle + offset + count, oracle + offset + remove, length - offset - remove);
+ memcpy(oracle + offset, insert, count);
+ length = length - remove + count;
+ expect(path, "work", revision, (PureSpan){oracle, length});
+ CHECK(old.body.size == previous && !memcmp(old.body.data, before, previous));
+ pure_store_release(&old);
+ }
+ int64_t latest = revision;
+ CHECK(pure_store_splice(path, "work", latest - 1, 0, 0, (PureSpan){insert, 1}, PURE_OBJECT_LIMIT, &revision) == PURE_CONFLICT);
+ CHECK(revision == latest);
+ CHECK(pure_store_splice(path, "work", latest, SIZE_MAX, 0, (PureSpan){0}, PURE_OBJECT_LIMIT, &revision) == PURE_LIMIT);
+ CHECK(pure_store_splice(path, "work", latest, 0, SIZE_MAX, (PureSpan){0}, PURE_OBJECT_LIMIT, &revision) == PURE_LIMIT);
+ CHECK(pure_store_splice(path, "work", latest, length + 1, 0, (PureSpan){0}, PURE_OBJECT_LIMIT, &revision) == PURE_LIMIT);
+ /* Rejected before reading the intentionally undersized insertion pointer. */
+ CHECK(pure_store_splice(path, "work", latest, 0, 0, (PureSpan){insert, PURE_OBJECT_LIMIT}, PURE_OBJECT_LIMIT, &revision) == PURE_LIMIT);
+ CHECK(pure_store_splice(path, "work", latest, 0, 0, (PureSpan){insert, 1}, length, &revision) == PURE_LIMIT);
+ CHECK(revision == latest);
+ expect(path, "work", latest, (PureSpan){oracle, length});
+ CHECK(pure_store_splice(path, "missing", 0, 1, 0, (PureSpan){0}, PURE_OBJECT_LIMIT, &revision) == PURE_LIMIT);
+ PureStoredView view;
+ CHECK(pure_store_get(path, "missing", 0, &view) == PURE_NOT_FOUND);
+ for (failed_stage = PURE_AFTER_HEADER; failed_stage <= PURE_BEFORE_RENAME; ++failed_stage) {
+ CHECK(pure_store_splice(path, "work", latest, 1, 3, (PureSpan){insert, 5}, PURE_OBJECT_LIMIT, &revision) == PURE_STORE_ERROR);
+ expect(path, "work", latest, (PureSpan){oracle, length});
+ }
+ failed_stage = PURE_BEFORE_DIR_SYNC;
+ CHECK(pure_store_splice(path, "work", latest, length, 0, (PureSpan){insert, 5}, PURE_OBJECT_LIMIT, &revision) == PURE_UNCERTAIN);
+ CHECK(revision == latest + 1);
+ failed_stage = -1;
+ memcpy(oracle + length, insert, 5); length += 5;
+ expect(path, "work", revision, (PureSpan){oracle, length});
+ CHECK(pure_store_splice(path, "work", revision, 0, length, (PureSpan){0}, PURE_OBJECT_LIMIT, &revision) == PURE_OK);
+ expect(path, "work", revision, (PureSpan){0});
+ char file[256];
+ snprintf(file, sizeof(file), "%s/obj-work", path);
+ int fd = open(file, O_WRONLY);
+ const unsigned char maximum[] = {255,255,255,255,255,255,255,127};
+ CHECK(fd >= 0 && pwrite(fd, maximum, 8, 8) == 8 && close(fd) == 0);
+ CHECK(pure_store_splice(path, "work", INT64_MAX, 0, 0, (PureSpan){0}, PURE_OBJECT_LIMIT, &revision) == PURE_LIMIT);
+}
+
+static void runtime(const char *path) {
+ PureProgram program;
+ char error[160];
+ CHECK(pure_program_load("examples/editor.pure", &program, error, sizeof(error)));
+ PureRuntime runtime;
+ PureWork slots[1];
+ PureHost denied = pure_store_host(path);
+ denied.write = NULL; /* no write effect grants no splice permission */
+ CHECK(pure_runtime_init(&runtime, slots, 1, &program, denied, 32));
+ PureTicket ticket = {0};
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "native", 0, 9, &ticket) == PURE_DENIED);
+ CHECK(!ticket.runtime && runtime.active == 0 && runtime.retained == 0);
+ CHECK(pure_runtime_restart(&runtime, &program, pure_store_host(path), 32));
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "native", 0, 9, &ticket) == PURE_OK);
+ CHECK(pure_runtime_cancel(ticket) && pure_runtime_release(ticket));
+ CHECK(!pure_runtime_step(&runtime));
+ PureStoredView view;
+ CHECK(pure_store_get(path, "native", 32, &view) == PURE_NOT_FOUND);
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "native", 0, 7, &ticket) == PURE_OK);
+ memset(pure_runtime_ingress(ticket, NULL), 0, 7);
+ CHECK(pure_runtime_ready(ticket) && pure_runtime_step(&runtime));
+ PureOutcome result;
+ CHECK(pure_runtime_result(ticket, &result) && result.status == PURE_LIMIT);
+ CHECK(pure_runtime_release(ticket) && runtime.commits == 0);
+ CHECK(pure_runtime_accept(&runtime, PURE_INPUT_WRITE, "native", 0, 9, &ticket) == PURE_OK);
+ unsigned char *input = pure_runtime_ingress(ticket, NULL);
+ memset(input, 0, 8); input[8] = 'x';
+ CHECK(pure_runtime_ready(ticket) && pure_runtime_step(&runtime));
+ CHECK(pure_runtime_result(ticket, &result) && result.status == PURE_OK && result.revision == 1);
+ CHECK(result.body.size == 1 && result.body.data == input + 8 && runtime.retained == 9);
+ expect(path, "native", 1, (PureSpan){(const unsigned char *)"x", 1});
+ CHECK(pure_runtime_release(ticket) && runtime.retained == 0 && runtime.active == 0);
+}
+
+int main(void) {
+ parser();
+ char path[] = "/tmp/pure-splice-check-XXXXXX";
+ CHECK(mkdtemp(path) && pure_store_init(path) == PURE_OK);
+ storage(path);
+ runtime(path);
+ DIR *entries = opendir(path);
+ CHECK(entries);
+ struct dirent *entry;
+ while ((entry = readdir(entries))) {
+ if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue;
+ CHECK(strncmp(entry->d_name, ".pending-", 9));
+ CHECK(unlinkat(dirfd(entries), entry->d_name, 0) == 0);
+ }
+ CHECK(closedir(entries) == 0 && rmdir(path) == 0);
+ puts("{\"splice_tests\":\"passed\",\"checks\":[\"authored-fields-and-atomic-parse-failure\","
+ "\"binary-edit-oracle-and-old-snapshot\",\"bounds-conflict-size-overflow\","
+ "\"publication-failures-and-uncertain-durability\",\"cancel-admission-and-borrowed-reply\"]}");
+ return 0;
+}
diff --git a/prototypes/connections/tui-budget.json b/prototypes/connections/tui-budget.json
new file mode 100644
index 0000000..1ca06b0
--- /dev/null
+++ b/prototypes/connections/tui-budget.json
@@ -0,0 +1,12 @@
+{
+ "profile": "linux-aarch64-gcc14-fixed-document-terminal-editor",
+ "binaries": {
+ "pure-edit-tui-fixed": {
+ "max_text_bytes": 32768,
+ "max_data_bytes": 1152,
+ "max_bss_bytes": 64,
+ "needed": ["libc.so.6"]
+ }
+ },
+ "scope": "Release-linked optional POSIX terminal editor for one build-time prepared document app, including the bounded document browser. The raised text ceiling reviews its measured 2,541-byte addition; default CLI and core ceilings are unchanged. Excludes libc, terminal emulator, kernel TTY buffers, heap and stack. Whole-process RSS, including 1,024-key browsing, is checked by check_tui.py on the recorded Linux AArch64 host."
+}
diff --git a/prototypes/connections/window-budget.json b/prototypes/connections/window-budget.json
new file mode 100644
index 0000000..511557e
--- /dev/null
+++ b/prototypes/connections/window-budget.json
@@ -0,0 +1,12 @@
+{
+ "profile": "linux-aarch64-gcc14-selected-native-document-authoring",
+ "binaries": {
+ "pure-edit-window": {
+ "max_text_bytes": 57344,
+ "max_data_bytes": 1800,
+ "max_bss_bytes": 64,
+ "needed": ["libgtk-4.so.1", "libgio-2.0.so.0", "libgobject-2.0.so.0", "libglib-2.0.so.0", "libc.so.6"]
+ }
+ },
+ "scope": "Review ceiling for the selected GTK document-and-definition host on Linux AArch64/GCC 14. Linked code sections and direct dependencies only; the measured 44 MiB whole-process RSS and shared GTK stack remain separate costs."
+}