Repository navigation
CONTRACT: fix(ui-server): commit inbox lifecycle writes on the write worker - #3014
Merged
Merged
Conversation
…cle-offloop-044 # Conflicts: # docs/decisions/scheduled-tasks.md # docs/decisions/sqlite-write-worker.md
# Conflicts: # docs/decisions/http-api-boundary.md # docs/decisions/session-principals.md # docs/decisions/sqlite-write-worker.md # docs/decisions/voice-permission.md # docs/plans/async-collaboration-requirements.md # docs/plans/async-collaboration.md # docs/plans/navigation-recovery.md
This was referenced Oct 26, 2026
schlessera
marked this pull request as ready for review
October 26, 2026 14:16
This was referenced Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3001
Refs #2850 (epic)
What changed
The hosted inbox now commits intake receipts and replay, lifecycle recovery and budget reconciliation, maintenance and heartbeat, cleanup claims and acknowledgements, interactive-share records, decisions, and hygiene review on the app's SQLite write worker at
synchronous=FULL. The transaction bodies keep their reads, mutations and change records together. Intake and decisions answer after commit, share tools queue behind their session bind, share start precedes backend execution, and share end precedes slot release. Boot stops before sweep or heartbeat if recovery fails.The missed
@internaltags onWsHost.inboxToolsandWsHostOptions.inboxToolsnow implement the existing #1053 narrowing ruling. The integration-contract paragraph namesinboxToolsexplicitly, the API report is regenerated, and the patch changeset names the narrowing. The concrete inbox helpers now await their commits.Why this shape
This uses the procedure-module pattern from #2933, #2949, #2992 and #2994 and the decision in
docs/decisions/sqlite-write-worker.md. Every procedure uses the shared queue, preserving commit order with journal and Activity. Standalone callers use the same code inline. File staging/application remain outside SQLite writes; completion still verifies authoritative receipts and bytes under the application lock. Disposable share lifetime locks stay held through unwind. Refusals keep their classes across the worker.The native timing wrappers also await the asynchronous bridge. The intake failure fixture installs its trigger in the shared schema, so it still injects a failure on the write connection. Moved source citations are updated.
Proof
Current candidate
e77b90c2f9dd6682234f4ba426d44fb08d392a91; merged base07fbce896099b87903bb994e3b6a939f232669fd. All package/root/preflight/pack commands use the shared two-slot heavy wrapper; native fixture commands use the exclusive native lock. The refresh preserves main's notice/local-exchange paragraphs and limits the remaining-writers edit to inbox.APP_CONNECTION_WRITE; 0 pass / 3 fail. Boot ordering separately failsINBOX_FAILED_RECOVERY_SUBMITS_NO_LATER_WRITESbefore the ordering correction. These are behavioral failures, not module-load failures.bunx --no-install tsc --noEmitpassed.heavy.sh, 4113 pass / 0 fail, 28462 assertions, 346 files, 2114.01 seconds. The complete current-main comparison (07fbce896099b87903bb994e3b6a939f232669fd) finished 4101 pass / 1 fail, 28421 assertions, 345 files, 2029.88 seconds. Its sole failure is the unchanged private-index advance test (private-index-cache.test.ts:647), filed as tests: private-index advance returns an empty rebound result in the package suite #3016; the shared-storage identity case passed.heavy.sh, 1966 pass / 0 fail, 74416 assertions, 179 files, 788.96 seconds.bun run check:pr --base origin/main: passed on the current head throughheavy.sh, including lint and 1204 fast invariant tests (0 fail, 7919 assertions, 83.51 seconds).heavy.sh; every publishable package packed, installed and passed its consumer probes.Completed receipts from previous candidate
b9b7d099ba362838f22407902c9d3a4b9fc70cc6, basec47483196f02c1098128207ce68c4f0de6b571ab(retained separately from the refreshed proof):STORAGE_SHARED_ONE_COLLECTIONin the unchanged shared-storage scan test. That complete file passes on the same head and base: 7 tests / 38 assertions each. Attribution is filed as tests: shared storage scan intermittently returns two collection IDs #3013. The complete current-main control passed the shared-storage case; its sole unrelated failure is in tests: private-index advance returns an empty rebound result in the package suite #3016. The refreshed-head package suite passes all 4113 tests; no storage implementation or fixture change was made. All 11 new inbox tests pass within the full run.AREAS_WRITABLEin Claude interactive/voice and pi interactive policy-boundary cases. The complete focused file passes on both head and base (19 tests, 587 assertions each); the complete base root suite passes 1966/1966 (74412 assertions). The unchanged full-head retry establishes variability, not a repair or cause. Receipts are recorded in tests: full suites intermittently lose writable scratch #3010, with the narrower observations in tests: the voice policy-write boundary case reports the scratch area unwritable #2923 and tests: Pi interactive policy boundary intermittently reports scratch unwritable #2987.NATIVE_AUTOMATIC_INDEX_COMPLETED: stale maintenance output: .brain-index/brain.db-shm, the existing ui-sdk: native index publication intermittently refuses changed database or sidecar stamps #2878 failure. The same command fails on basec47483196f02c1098128207ce68c4f0de6b571abwith the exact error (114.2 seconds vs 118.6 seconds on the branch); both diagnostic commands remain recorded as failed.Mutation receipts, rerun on current head
e77b90c2f9dd6682234f4ba426d44fb08d392a91(all nonzero exits with the actual named error line verified, then restored):APP_CONNECTION_WRITE.SQLITE_WRITE_BELOW_FULL.SQLITE_WRITE_BELOW_FULL.SQLITE_WRITE_BELOW_FULL.SQLITE_WRITE_BELOW_FULL.SQLITE_WRITE_BELOW_FULL.SQLITE_WRITE_BELOW_FULL.SQLITE_WRITE_BELOW_FULL.INBOX_THREAD_SEQUENCES_GAP_FREE_AFTER_ROLLBACK.INBOX_REFUSAL_CLASS_KEPT.INBOX_FAILED_RECOVERY_SUBMITS_NO_LATER_WRITES.SQLITE_WRITE_BELOW_FULL.INBOX_TICK_COMMITTED_BEFORE_REPLY.INBOX_CLEANUP_COMMITTED_BEFORE_REPLY.SQLITE_WRITE_BELOW_FULL.SQLITE_WRITE_BELOW_FULL.SQLITE_WRITE_BELOW_FULL.Native pi UID 1000 lag comparison under three
dd ... conv=fsyncwriters, with CPU profiles and app-turn/worker timing joined: before sourcee69ade405plus timing probes had no window ≥250 ms afterready; after source62919c407plus the same probes had one at 273 ms. The latter has no app-connection turn wait over 20 ms, overlaps a workerupsertSessionlasting 288 ms, and has no inbox frame samples; it remains unattributed. This is not a claim of overall lag improvement. These ordinary native turns invoke no-op share start/bind checks and a boot heartbeat, but create no bound share, intake, hygiene review or expired inbox lease afterready; this cell cannot qualify nonempty lifecycle traffic. The focused worker tests exercise those writes directly.Checklist
docs/reflect the change, or nothing documented moved.docs/decisions/provider-history.md): the provider-history guard passes, or nothing on a turn's path changed.Anything left open
Draft only. All required local proof passes on the current head. The completed current-main package control has one unrelated failure in #3016. Refreshed root, preflight, pack smoke, native matrix, identity and focused proof pass. The coordinator owns readiness, complete selected CI confirmation and merge. Scratch variability remains in #3010, storage collection attribution in #3013, the current-main private-index advance observation in #3016, and the optional observation-timing index-publication failure in #2878. Native nonempty-inbox traffic is outside the existing hosted cell; no general performance guarantee is claimed.