Private upload staging and exactly-once crash recovery (#759b) #788
Open
kayg
wants to merge 11 commits from
fix/private-staging-759b-r2 into dev
pull from: fix/private-staging-759b-r2
merge into: kayg:dev
kayg:main
kayg:feat/style-sheet-fixes
kayg:storage/wal-checkpoint-off-save-1051
kayg:t3/paged-search-reconcile-final
kayg:feat/pass8
kayg:review/calendar-2
kayg:fix/shared-row-swipes
kayg:feat/contrast
kayg:dev
kayg:feat/collections-db
kayg:fix/instant-keys-1056
kayg:feat/money-round
kayg:perf/stalls-1054
kayg:wip/tiering-v3-cold4
kayg:wip/tiering-v3-cold5
kayg:port/rows-actions
kayg:port/rows-drop
kayg:port/hidden-blocks
kayg:port/rows
kayg:port/port-tables
kayg:port/port-tables-2
kayg:t3/mail-1011-liveness
kayg:port/devices
kayg:port/port-attachments
kayg:port/port-attachments-2
kayg:port/port-attachments-3
kayg:docs/design-consistency
kayg:docs/engineering-standards
kayg:fix/rusqlite-0.41-rustsec-2026-0459
kayg:feat/iphone-fixes
kayg:shared/restore-and-stale-918-919
kayg:fix/phone-top-band-contrast
kayg:feat/notes-approve
kayg:perf/soak-max-gate
kayg:feat/files-s1-identity
kayg:fix/lifecycle-event-id
kayg:feat/quickfix
kayg:wip/tiering-v3-cold
kayg:perf/web-mockup-frame-fixes
kayg:port/contacts-merge
kayg:port/contacts-edit
kayg:test/shared-room-no-deleted-text
kayg:perf/first-paint-credits
kayg:fix/shared-history-after-grant
kayg:fix/phone-swipe-regressions
kayg:feat/contrast-r1
kayg:review/sharing-pr3-review
kayg:feat/tiering-v3-s2-tags
kayg:feat/folder-drop
kayg:fix/deskpills-lazy-share
kayg:feat/sharing-s1-pr3
kayg:tmp/money-round-before
kayg:fix/phone-pane-backdrop-roots
kayg:fix/palette-preload-chips
kayg:fix/invite-defaults
kayg:port/tasks-matrix
kayg:fix/restore-green-gates
kayg:fix/sharing-fast-path-hardening
kayg:t3/photos-s1
kayg:feat/tiering-v3-s1-namespace
kayg:notes-archive-hide
kayg:feat/tasks-actions
kayg:t3/photos-plan-slice-one
kayg:feat/whiteboard-s1
kayg:t3/paged-search-reconcile
kayg:t3/smooth-pane-transitions
kayg:t3/index-position-startup-scan
kayg:feat/dav-transport
kayg:feat/imap-notes-fetch
kayg:feat/imap-notes-projection
kayg:feat/imap-notes-readonly
kayg:feat/imap-notes-auth
kayg:feat/imap-notes-server-foundation
kayg:docs/undo-block-ids-plan
kayg:fix/undo-768
kayg:proto/block-identity-v7d
kayg:issue/carddav-read-perf-fix-r2
kayg:issue/carddav-read-r2
kayg:docs/imap-766-plan-v2
kayg:docs/imap-notes-plan
kayg:docs/quota-plan-2
kayg:fix/parallel-test-flakes
kayg:feat/contacts-companion-pure
kayg:docs/calendar-backend-v2-plan
kayg:feat/calendar-ical-converter
kayg:docs/tasks-writes-v2-plan
kayg:docs/carddav-writes-v2-plan
kayg:docs/contacts-import-v2-plan
kayg:issue/610-pm-midnight
kayg:feat/calendar-v2-s1-containment
kayg:docs/dav-recorder-v2-plan
kayg:plan/previews-865
kayg:plan/save-log-durable-entry
kayg:fix/e2e-data-on-ram
kayg:feat/appwindow3
kayg:feat/appwindow2
kayg:feat/appwindow
kayg:feat/money-p1
kayg:feat/keys-sheet
kayg:review/calendar-2-themes
kayg:feat/smooth-cursor
kayg:fix/float-style
kayg:review/calendar-2-float
kayg:release/2026-11-06-hotfix
kayg:archive/port/rows-drop-code
kayg:archive/port/rows-actions
kayg:archive/port/rows
kayg:scratch/tasks-894-ui-gates
kayg:review/calendar-2-night-wip
kayg:release/2026-11-05
kayg:archive/feat/tiering-v3-s1-namespace
kayg:archive/flaky/rows-drop-fixed
kayg:archive/flaky/rows-actions
kayg:archive/feat/tiering-v3-reader
kayg:archive/feat/tiering-v3-roots
kayg:archive/flaky/rows
kayg:sim/bm15-final
kayg:sim/bm15-fix
kayg:sim/bm15-bis-932
kayg:sim/bm15-bis-909
kayg:sim/bm15
kayg:sim/bm15-bis-887
kayg:perf/tiering-option-b
kayg:port/style-3
kayg:port/style-2
kayg:port/style
kayg:fix/sw-lazy-precache
kayg:fix/vim-w-waits-for-save
kayg:fix/signout-test-races
kayg:fp-scratch/all
kayg:sim/bm15-first-paint
kayg:archive/bm15/rows-drop
kayg:archive/bm15/rows-actions
kayg:fix/palette-snippet-contrast
kayg:archive/bm15/rows
kayg:archive/bm15/hidden
kayg:archive/plan/save-log-durable-entry
kayg:mock/money-fix2
kayg:archive/fix/e2e-data-on-ram
kayg:mock/appearance-all
kayg:mock/pill-press
kayg:archive/docs/design-consistency
kayg:mock/auto-swipes
kayg:mock/mail-actions
kayg:archive/feat/mail-p1
kayg:mock/money-static
kayg:archive/review/standards-917
kayg:archive/docs/engineering-standards
kayg:perf/tiering-761-fix
kayg:mock/type-audit
kayg:mock/third-pane
kayg:feat/contacts-import-v2-s1
kayg:perf/executor-hot-path
kayg:archive/port/hidden-blocks
kayg:archive/port/devices
kayg:scratch/executor-on-894
kayg:scratch/executor-spans2
kayg:scratch/executor-spans
kayg:train/2026-11-03-bm14c
kayg:archive/port/rows-drop
kayg:feat/tiering-761-d-scale
kayg:feat/tiering-761-c-index
kayg:feat/tiering-761-b-reader
kayg:archive/review/sharing-pr3-review-9fec3d1f
kayg:train/2026-11-03-bm14b
kayg:perf/ports-lazy-budgets
kayg:feat/tiering-761-a-migration
kayg:train/2026-11-03-bm14
kayg:train/2026-11-03-bm12
kayg:archive/review/sharing-pr3-review
kayg:archive/feat/sharing-s1-pr3
kayg:train/2026-11-03-bm11
kayg:archive/feat/imap-notes-fetch
kayg:train/2026-11-03-bm10
kayg:archive/review/sharing-pr3-review-code
kayg:archive/plan/previews-865
kayg:train/2026-11-02-bm9
kayg:archive/port/port-attachments-3
kayg:archive/port/contacts-merge
kayg:fix/motion-audit-859
kayg:train/2026-11-02-bm8
kayg:archive/scratch/bm8-prep
kayg:archive/port/port-pickers
kayg:archive/port/port-tables-2
kayg:archive/port/port-tables
kayg:archive/feat/sharing-s1-pr3-code
kayg:archive/scratch/bm7-fixed
kayg:train/2026-11-02-bm7
kayg:archive/fix/parallel-test-flakes-code-minipc01
kayg:train/2026-11-02-bm6
kayg:docs/imap-766-readonly-slice
kayg:feat/dav-recorder-v3
kayg:research/788-diagnosis
kayg:archive/fix/parallel-test-flakes
kayg:archive/perf/pr792-cold-index-edit
kayg:docs/sharing-slice-1
kayg:archive/docs/imap-766-plan-v2
kayg:feat/dav-recorder-v2
kayg:archive/docs/dav-recorder-v2-plan
kayg:spike/imap-766-s0-cases
kayg:archive/fix/undo-768
kayg:feat/dav-recorder
kayg:archive/docs/contacts-import-v2-plan
kayg:archive/feat/calendar-ical-converter
kayg:feat/contacts-import
kayg:perf/cold-growth-on-764
kayg:perf/cold-growth-on-tiering
kayg:archive/docs/tasks-writes-v2-plan
kayg:archive/docs/calendar-backend-v2-plan
kayg:archive/feat/contacts-companion-pure
kayg:feat/tasks-set-status
kayg:feat/tasks-move-reorder
kayg:archive/docs/carddav-writes-v2-plan
kayg:archive/feat/calendar-v2-s1-containment
kayg:feat/tasks-delete-promote-duplicate
kayg:archive/feat/dav-transport
kayg:archive/fix/carddav-rebuild-r1
kayg:archive/fix/carddav-retention-r1
kayg:feat/carddav-writes
kayg:perf/quota-on-tiering
kayg:perf/quota-simple
kayg:perf/cold-growth-on-quota-stack
kayg:feat/calendar-identity
kayg:feat/calendar-event-parser
kayg:feat/calendar-props-maps
kayg:port/glass-when-ring
kayg:feat/tiering-761-s1
kayg:wip/10by32-01-impl-759b-scratch-20261030
kayg:wip/6by32-01-bm3-webkit-pause-20261030
kayg:wip/10by32-01-bm3-chromium-pause-20261030
kayg:wip/6by32-01-tier-761-s1-pause-20261030
kayg:spike/imap-766-s0
kayg:wip/6by32-02-calternal-pause-20261030
kayg:wip/8by64-01-review-688-pause-20261030
kayg:wip/6by32-01-verify-744-pause-20261030
kayg:wip/6by32-01-verify-742-pause-20261030
kayg:fix/private-staging-759b
kayg:wip/6by32-01-review-748-pause-20261030
kayg:wip/6by32-01-review-733c-pause-20261030
kayg:wip/6by32-01-review-733b-pause-20261030
kayg:wip/6by32-01-perf-idle-8-pause-20261030
kayg:wip/6by32-01-perf767-base-pause-20261030
kayg:wip/6by32-01-perf767b-767-pause-20261030
kayg:wip/6by32-01-perf767b-764-pause-20261030
kayg:wip/6by32-01-perf767-767-pause-20261030
kayg:wip/6by32-01-perf767-764-pause-20261030
kayg:wip/6by32-01-lists-b-pause-20261030
kayg:wip/6by32-01-ids-verify5-pause-20261030
kayg:wip/6by32-01-ids-verify4-pause-20261030
kayg:review/calendar-month
kayg:wip/10by32-02-undo-768-20261030
kayg:test/ids-verify3
kayg:wip/10by32-02-bm3-chromium-20261030
kayg:wip/10by32-01-review-753-20261030
kayg:wip/10by32-01-perf-idle-2-20261030
kayg:wip/10by32-01-bm2-webkit2-20261030
kayg:plan/759b-staging
kayg:train/2026-10-30-bm2
kayg:review/758b-tests
kayg:review/758-tests
kayg:review/764d-tests
kayg:review/767b-tests
kayg:review/preview-2026-10-29
kayg:review/767-tests
kayg:docs/tiering-731-plan
kayg:wip/c6b02-when2
kayg:wip/c6b02-tasks-create-fix5
kayg:wip/c6b02-settings-frost-mock
kayg:wip/c6b02-settings-frost-base
kayg:wip/c6b02-settings-frost
kayg:wip/c6b02-ring
kayg:wip/c6b02-review-733d
kayg:wip/c6b02-bm1-full-a
kayg:wip/compute02-when-field
kayg:wip/compute02-webkit-lists-repro
kayg:wip/compute02-train-bl2-dev
kayg:wip/compute02-dev-green-pw164
kayg:docs/deploy-plan
kayg:review/764c-tests
kayg:review/764b-tests
kayg:review/748g-tests
kayg:review/764-tests
kayg:review/759b-tests
kayg:fix/storage-owner-liveness-642
kayg:fix/storage-fix-7
kayg:wip/compute02-storage-fix-7
kayg:review/759-tests
kayg:feat/tiering-731
kayg:wip/tiering-731-first-attempt
kayg:wip/compute02-storage-fix-1
kayg:review/754g-tests
kayg:perf/idle-honest-2
kayg:review/754f-tests
kayg:review/754e-tests
kayg:review/755-tests
kayg:review/754d-tests
kayg:review/754c-tests
kayg:review/754b-tests
kayg:review/754-tests
kayg:fix/storage-private-tmp-642-dev
kayg:wip/compute02-verify-750
kayg:test/ids-verify5
kayg:test/ids-verify4
kayg:fix/storage-exact-file-quarantine-642
kayg:wip/compute02-verify-740
kayg:perf/one-flush-save
kayg:review/calendar-static
kayg:wip/compute02-verify-737
kayg:review/indexing-ring
kayg:review/when-field-2
kayg:wip/compute02-review-733
kayg:proto/block-identity-2-review
kayg:proto/block-identity-review
kayg:wip/c6b02-tc-design
kayg:review/when-field
kayg:issue/tasks-create-ids
kayg:issue/tasks-create
kayg:review/combined
kayg:wip/compute02-review-combined
kayg:review/task-polish
kayg:review/top-buttons
kayg:review/q1-q5
kayg:train/2026-10-26-bl2
kayg:archive/wt-398h
kayg:archive/train-bm-proptest-seed
kayg:archive/integ325-293
kayg:archive/integ325-ci
kayg:archive/client-auth-review-baseline
kayg:archive/wt-sim-4853
kayg:archive/wt-sim-4811
kayg:archive/wt-448m
kayg:archive/wt-398a-allocator
kayg:issue/calendar-adr
kayg:archive/old/train/2026-10-23bk2
kayg:archive/old/train/2026-10-23bk
kayg:issue/469-mockup-9a
kayg:issue/smart-tasks-mockup
kayg:issue/469-menus
kayg:issue/652-signout-flake
kayg:issue/652-history-fix7
kayg:issue/652-history-fix6
kayg:archive/old/issue/spring-check-perf
kayg:issue/spring-check-perf
kayg:issue/659-rename-fast
kayg:archive/old/train/2026-10-21ar
kayg:issue/search-hardening-3
kayg:issue/652-history-fix5
kayg:issue/660-port-sheets-glass
kayg:issue/652-history-fix4
kayg:issue/652-history-fix3
kayg:issue/652-history-fix2
kayg:issue/652-history-flake
kayg:train/2026-10-21an
kayg:issue/settings-admin-port
kayg:issue/search-port
kayg:train/2026-10-20am
kayg:issue/storage-split-fix2
kayg:issue/storage-split
kayg:archive/old/issue/folder-ids-fix
kayg:train/2026-10-20al
kayg:archive/old/issue/folder-ids
kayg:train/2026-10-20ak
kayg:issue/tables-mockup
kayg:train/2026-10-19aj
kayg:train/2026-10-19ai
kayg:issue/469-merge-fixes
kayg:issue/sidebar-band
kayg:archive/old/issue/608-settings-spec
kayg:train/2026-10-19ah
kayg:issue/swipe-offscreen
kayg:train/2026-10-19ag
kayg:archive/old/issue/590-nlp-adr
kayg:archive/old/issue/587-event-after-write-2
kayg:train/2026-10-19af
kayg:archive/old/issue/587-event-after-write
kayg:issue/469-pill-room-c
kayg:issue/469-pill-room
kayg:train/2026-10-19ae
kayg:issue/469-narrow-handle
kayg:issue/397-ios-swipe-2
kayg:archive/old/issue/adrs-photos-files-tasks
kayg:issue/469-desk-fixes
kayg:archive/old/issue/auto-update-adr
kayg:issue/469-filter-gap
kayg:issue/469-port-1b
kayg:issue/442-opacity-flake
kayg:archive/397-ios-swipe-2
kayg:issue/327-web-fast-3
kayg:archive/old/issue/469-port-1
kayg:issue/469-port-1
kayg:issue/327-web-fast-2
kayg:archive/old/issue/327-web-fast
kayg:archive/old/issue/425-stt-bench-vq1
kayg:archive/old/issue/445-no-bleed
kayg:archive/old/issue/400-swipe-mockup-2
kayg:issue/426-client-review
kayg:issue/426-client-2
kayg:issue/426-client
kayg:archive/old/issue/476-safe-area-lab
kayg:archive/445-top-light-2
kayg:archive/old/issue/445-top-light
kayg:issue/471-blocks-mockup
kayg:archive/old/issue/448-links-app-2
kayg:archive/old/issue/448-links-app
kayg:archive/old/issue/398-cold-links
kayg:issue/434-442-small-2
kayg:issue/434-442-small
kayg:archive/old/issue/398-unload
kayg:archive/old/issue/445-bottom-band
kayg:issue/445-bottom-band
kayg:issue/351-rem-3
kayg:archive/312-views-mockup
kayg:issue/351-rem-2
kayg:issue/351-rem
kayg:archive/old/issue/327-first-note
kayg:issue/395-width-phone
kayg:archive/old/issue/327-typing
kayg:issue/396-ios-edges
kayg:issue/397-ios-swipe
kayg:archive/398-allocator
kayg:archive/old/issue/327-notes-index
kayg:issue/345-347-contrast-empty-2
kayg:archive/old/issue/44-arenas
kayg:issue/44-arenas
kayg:archive/integ325
kayg:archive/old/issue/327-perf-harness
kayg:archive/old/issue/44-thp
kayg:issue/44-thp
kayg:archive/old/issue/285-sticky-pills
kayg:archive/old/issue/44-trim-3
kayg:issue/44-trim-3
kayg:archive/old/issue/165-cards
kayg:archive/old/issue/165-picker-2
kayg:archive/old/issue/212-multi-select
No reviewers
Labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
kayg/calternal!788
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/private-staging-759b-r2"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Round 2 correction complete:
ef9a08d9R2-P1 guard ownership and R2-P2 changed-device regression are fixed. The held record remains shared until durable result confirmation; existing Ready records govern restart. Exact reproduction, 32 await-boundary cancellation cases, focused tests, full workspace, separate 1,000-round kill loop, Clippy and fmt all passed on dev-01. FINAL independent review (round 3) is pending. No merge. Native macOS, the complete #771 matrix and the other documented review gaps remain open.
Latest status table, exact commands, red/green evidence and source-byte provenance: #788 (comment)
Round 2 correction design
Keep each unresolved upload owned by the shared record map throughout repair and engine resolution. Reconciliation borrows a bounded completion snapshot under the placement lock and removes the held record only after the engine confirms a durable result. Cancellation before that point leaves both the live content guard and the existing on-disk Ready record intact; restart continues to honour that record. No new record format, detached lifetime, or disk writes. Extra transient memory: one completion snapshot, at most 16 KiB; unchanged O(Kheld) scan and O(1) per-result bookkeeping.
Final gates requested for this correction: full workspace, separate 1,000-round SIGKILL loop, workspace all-target Clippy with warnings denied, formatting on dev-01. Native macOS and the complete #771 matrix remain open; the prior three-size measurements remain an early signal only. Never merge.
Implements #771 / #759b. Uploads remain private until exclusive publication; every placed file keeps its original result authority until the engine commits it exactly once. Fixes all three carried-forward P1s and the retry/cancellation gaps reproduced during this resume. Do not merge without independent review and the remaining platform/matrix gates.
Plan and costs
Stream N bytes in C paced writes: O(N) I/O/hash work, O(1) per-upload buffering and metadata; completion records are capped at 16 KiB, publication at 1,000 candidates. No per-chunk receipts, hashes, xattrs or added syncs. Publication retains payload fsync and both rename-parent fsyncs; index and engine durability remain intact. Recovery is O(pending records × bounded candidate lookups), plus scratch entries. Live retry reconciliation and unresolved-content guards scan the global held-result map O(Kheld), filtered to the user; large concurrent held-result populations remain unmeasured.
Measured plan adjustment: construction now writes Scratch atomically without fsync, matching Ready replacement. Both are transient metadata with a process-death guarantee, not a power-loss guarantee. The full record is written and closed, then renamed before publication. Scratch deletion authority comes from the payload inode proof, independently of the pending record. This removes two disposable-record flushes measured at about 8 ms/upload in the syscall diagnostic; no acknowledged file/result durability barrier was removed. Retirement remains unsynced.
killing_an_upload_at_every_boundary_settles_exactly_oncea_refused_upload_killed_while_being_given_up_leaves_nothing_owedkilling_recovery_while_cancelling_a_ready_upload_still_settlesa_retry_after_a_failed_flush_indexes_the_file_so_new_keys_do_not_duplicate_it;a_retry_keeps_its_record_until_both_directory_sync_and_index_repair_succeeda_new_key_after_a_failed_flush_settles_the_original_before_deduplicating;concurrent_keys_for_the_same_bytes_keep_one_file_and_one_added_eventa_changed_device_number_after_restart_still_finds_the_placed_filestorage_locks; ordinary-server kill loopFindings status
Completion.devcomparisonDev advanced during verification. The branch merges
e283b132and resolves the two conflicts by keeping adapter staging under the raw request key while execution/reconciliation use the same action-scoped key. Pending completions pin both legacy raw and scoped receipts. Addedresolving_a_scoped_committed_result_never_records_it_againandresolving_an_unscoped_legacy_receipt_replays_without_a_new_event. The unadapted integration reproduced double journal commits, expired pins and three missed keyed test faults; see the integration evidence comment.Validation on dev-01
Nix tools,
~/bin/slot, cargo-j4; no builds/tests on control or perf machines. Final integrated head:ba86c6f6762b56ffeffae2decb7687ca91254930, including deve283b132. All six manual gates passed. VM source matches the pushed head except required uncommitted Nix shell files; control worktree is clean.Final kill distribution: 333 before any state / 561 in scratch / 22 placed-and-owing / 84 finished. Logs on dev-01:
~/resume759b-{focused,release,workspace,kill-loop,clippy,fmt}.log; orchestration log~/resume759b-final-gates5.log. Prior pre-integration logs are retained in~/resume759b-first-gates/and~/resume759b-unsynced-gates/.At
7f6a2928: focused tests 35 attachments + 89 fsio passed; full workspace completed through doc tests (1,238 passed, 20 ignored, zero failures across 89 summaries); separate 1,000-round SIGKILL loop passed in 68.76 s (330 before state / 540 scratch / 24 placed-and-owing / 106 finished), all settled exactly once. Initial Clippy caught an inherited disallowed test write; it now useswrite_atomic. Red logs and corrected test setup are recorded in the regression-evidence comment. Initial benchmark below is retained.Perf-01 comparison
Unchanged fixture from
wip/10by32-01-impl-759b-scratch-20261030@1e6e32d7,handover/759b/upload_bench.py; SHA2562f5110702d483678de7a7e91bb09a15398675554d33947c767fa7c366b8856c6.Unchanged PR #787 /
perf/vm-setupharnessperf/vm/upload-bench.sh; SHA256c25c70c8678030218a458d2d037310f7bdc277b17bd7109b11988ebd7ab14956.Fixed dev runtime baseline
d83e54db(same binary as #759), SHA2562ac46c102712f07402b2327f6b6a0eec66765fe67a1f7106f2d5900260eb66e8. This is a pinned comparison, not a claim to benchmark subsequent moving dev changes.Each comparison uses 10 balanced alternating pairs (odd dev→head, even head→dev), one harness rep/version/pair, fresh fixture data, one continuous perf lock; ext4
/dev/sdb1. Report median paired head/dev throughput; unchanged target ≥95%. Guest latency is bimodal as already noted on #759. Binaries built on dev-01 and relayed via control with matching SHA256 at all three hops.7f6a2928/ devInitial head binary SHA256
c4e7b813abbab228673ac90fa12e9530c7fc33f80a19f97075759856259c79f3. Initial raw output: perf-01~/perf/out-upload-759b-7f6a2928/; all 20 reps rc=0. After removing disposable Scratch flushes, source commit41b9f382passed all six gates (including full workspace and a 1,000-round kill loop: 342 before state / 543 scratch / 28 placed-and-owing / 87 finished, 71.61 s). The intermediate ten-pair benchmark reached 129.40% / 118.61% / 101.18%; raw~/perf/out-upload-759b-unsynced/, binary SHA256492972965ed982d48d1d7d13dc0ac07ee48d4bfff284defb94cf355d568e6670. These are intermediate results before the subsequent dev integration, not substituted for the final-head results below. Final binary SHA25622a80c38ff9aac7a40afe036dc116a7a27659ebddc791d7d8beb45000e25d6a5(dev-01 = control = perf-01). All 20 final reps rc=0. Raw output: perf-01~/perf/out-upload-759b-ba86c6f6/, including input hashes and alternating order. Per rep: 200 measured 4 KiB uploads, 40 × 4 MiB, 5 × 128 MiB, plus the fixture's unchanged warmups. The table above uses medians of paired ratios, which need not equal ratios of per-version medians below.Decisions: retain existing r2 history; merge dev deployment tooling (
a7dc49d6) and current dev receipt scoping (ba86c6f6) and retain offline lock-family guidance. Process-death recovery is the stated crash scope. Same-UID modifications inside private app-owned scratch remain outside scratch preservation; public/adopted outside bytes remain protected. No deployment, production access or merge performed.Round-1 independent implementation review, carried forward from the resume brief. The full original review text was not found on an existing implementation PR (this branch had none) or in the #771/#759 comments; this is a summary of its three P1s, not a new independent review.
recovery.rs:437comparedCompletion.dev. Device numbers may change across reboots on btrfs/ZFS/NFS/overlay, so a placed upload could become unresolvable. Locate within the recorded destination by inode/size without trusting persisted dev.place.rs:190/publish.rs:62could delete scratch while leaving a Ready record and no public file. Restart could not distinguish this from a user moving a published file. Retract/mark cancellation before scratch removal, and cover it at the attachments layer with SIGKILL tests.reconcile_keyatrecovery.rs:362committed the result without re-syncing the destination or updating the index. A later same-bytes upload could make a second copy. Repeat durability/index work before commit, and test same-key retry followed by a new key.These are fix-first findings. Status and regression evidence are tracked in the PR description. Cheap additional fixes already on r2 include recovered-intent component validation, distinct recovery destinations for successive same-name strangers, and the idempotency-pin registration diagnostic. Remaining gaps will be listed as follow-ups rather than represented as verified.
Regression evidence for implementation head
7f6a2928f02921dfbfea6297993927e6572cb729(dev-01, Nix tools, build-slot wrapper, cargo-j4).The inherited red-state logs were preserved before restoring the pushed fixes.
r2-before.logshows all three original P1 regressions failing: changed device number becomes a missing placed file; retry after failed flush savesflush-eio 2.jpg; failed publication plus crash leaves the person paused.r2-before2.logshows both additional fsio regressions failing without r2's intent-name validation and per-inode stranger destination fixes.This resume also reproduced:
resume759b-cancel-red.log: a second kill during cancellation recovery leaves Ready with no payload/public file. Recovery now atomically downgrades never-published Ready to Scratch before unlinking payload.resume759b-newkey-red.log: a replacement key immediately after the failed flush savesnew-key-after-flush 2.jpg; dropping the old server also fails to release its attachment owner because of the engine/plugin Arc cycle. Reconciliation now settles earlier placements before any upload, tracks public results under the placement lock, and uses weak engine/pin back-references.Fresh corrected focused command:
Test setup corrections are disclosed: the new concurrent-upload check initially exceeded the existing four-upload per-person admission limit (eight requests produced the expected 429); it now tests four admitted concurrent clients. The strict publication-order expectation now includes the new
publish.flushfault boundary between rename and after-sync. Neither product admission nor durability assertions were relaxed. The original failed logs remain preserved.Full workspace, separate 1,000-round SIGKILL rerun, release build and alternating perf-01 comparison are still running/pending; this comment does not claim those gates passed.
Initial perf gate for
7f6a2928missed the ≥95% target: median paired throughput was 93.44% of dev for 4 KiB, 90.66% for 4 MiB, and 104.39% for 128 MiB. Ten balanced alternating pairs on perf-01, unchanged #759 fixture and #787 harness, all 20 reps rc=0. Raw evidence:~/perf/out-upload-759b-7f6a2928/. Baseline is pinned dev runtimed83e54db.A separate syscall diagnostic (not substituted for the budget run) found two durable pending-record flushes costing about 8 ms/upload. The concrete plan was updated in this PR before changing Scratch construction to the existing atomic unsynced record helper. Ready already uses that helper. Process death leaves a fully installed old/new record; inode provenance independently authorizes scratch cleanup. The payload, publication directories, index and engine retain their durability barriers. This narrows the metadata work within the existing process-death claim; it does not claim power-loss recovery of transient records.
Focused 35 attachments + 89 fsio tests and the release build passed after that change. Full workspace, separate 1,000-round SIGKILL rerun, Clippy and a fresh ten-pair perf comparison are running. The original failed perf results remain in the PR description regardless of rerun outcome.
Dev-integration regression evidence at final integrated source
ba86c6f6762b56ffeffae2decb7687ca91254930.While gates were running, dev advanced to
e283b132with action-scoped idempotency receipts. A mechanical merge was unsafe: recovery's raw key missed a normally committed scoped receipt and recorded a second event; raw pins no longer protected scoped receipts past retention.resume759b-integration-red.logreproduced failures inkilling_an_upload_at_every_boundary_settles_exactly_once(recovery committed twice) anda_pinned_key_is_still_there_after_the_engine_restarts_past_retention. Three attachment recovery tests also exposed that their keyed commit fault injections needed the new internal scoped key:an_uncertain_commit_keeps_the_file_the_record_and_the_retry_gate_until_it_resolves,the_same_key_with_other_content_conflicts_instead_of_committing_the_wrong_thing, anda_placed_file_that_cannot_be_found_blocks_only_that_person_and_says_why.The added
resolving_a_scoped_committed_result_never_records_it_againwas run red independently (resume759b-scoped-red.log, assertion: recovery finds the normal action's receipt). Resolution now shares execute's scoped claim/storage key and legacy raw-receipt fallback. Attachments correlate adapter staging by the original public key and pin both receipt formats. Test fault injections were moved to the actual scoped store key; original assertions remain intact. Added legacy receipt replay coverage too.Focused integration command
cargo test --locked -p calternal-engine -p calternal-attachments -p calternal-fsio -j4 --no-fail-fastpassed (35 attachments, 94 fsio, 21 engine; one engine perf-only test ignored). Final source is pushed; full workspace, 1,000-round kill loop, Clippy, formatting, release and alternating perf reruns are pending. No claim of final acceptance yet.WIP: Private upload staging and exactly-once crash recovery (#759b)to Private upload staging and exactly-once crash recovery (#759b)Final verification for
ba86c6f6762b56ffeffae2decb7687ca91254930is complete. All six manual dev-01 gates passed, including the full workspace through doc tests (1,284 passed / 20 ignored / 0 failed) and a separate seeded 1,000-round SIGKILL loop (1,000 uploads all settled exactly once; 333 before state / 561 scratch / 22 placed-and-owing / 84 finished; 75.52 s). Focused tests: 35 attachments, 94 fsio, 21 engine passed, one engine perf test ignored. Release build, workspace Clippy with warnings denied, and formatting passed. Exact commands are in the PR description.Final ten-pair alternating perf-01 comparison against fixed dev runtime
d83e54dbpassed the unchanged ≥95% throughput target at every size: 4 KiB 139.02%, 4 MiB 119.75%, 128 MiB 103.11% (median paired head/dev ratios). All 20 reps rc=0. Exact unchanged fixture/harness, hashes, medians, paired p95 ratios, initial failed measurements and intermediate measurements are retained in the description. Final binary SHA256:22a80c38ff9aac7a40afe036dc116a7a27659ebddc791d7d8beb45000e25d6a5; verified at dev-01, control and perf-01. Raw final output: perf-01~/perf/out-upload-759b-ba86c6f6/.The branch includes dev
e283b132, with scoped/legacy idempotency reconciliation and pins covered. Control worktree is clean; VM source is the same head except uncommitted required Nix shell files. The first PR comment remains the original round-1 review summary. Independent review of this final head, native macOS proof, full #771 matrix, held-result-map scaling and multi-source pin composition remain explicitly open. No merge or deployment performed.Independent review, round 2
verdict: fix first at
ba86c6f6762b56ffeffae2decb7687ca91254930. no new P0; one newly reproduced P1 (duplicate save after cancellation) and one new P2 test regression. the normal retry fixes work, but the retry's own cancellation is unsafe. native macOS and the full #771 matrix also remain acceptance gaps.reviewed the PR body/comments, approved plan including pinning/offline upgrade, original round-1 report recovered from its saved agent transcript, and implementation. no product changes or pushes. control host used only for reading/orchestration; tests ran on dev-01 in an isolated reviewer worktree.
round-1 status
IDs below refer to the original report's numbered findings, including the P2/P3 items omitted from the first PR comment. “verified” means the stated fix is present; test limitations are explicit.
locateuses inode/size and regular-file type. the shipped changed-device test is vacuous after receipt scoping; see R2-P2 below. correcting its fault key and requiring a pending completion makes the test pass.publish_withretracts before discarding; refusal SIGKILL tests now include the attachments record. recovery also atomically downgrades Ready before deleting never-published payload. both refusal and second-recovery-crash tests pass.a_second_stranger_with_the_same_name_is_kept_beside_the_firstasserts separate recovered destinations and passes. not a proof against returning the same inode to the same source.open_sub/plain_parts. forged../payloadregression preserves source and reports damaged intent; passes. test specifically covers entry traversal, not every source variant.None. Linux ACL tests do not prove Darwin inheritance.owners.rs:224–239removes registry entry whileself.entrystill owns the old descriptors; automatic field drop happens after the registry guard is gone.open_instill performs stat/open under global mutex. existing lock tests do not force the final-drop/reopen interval.clean == falsestill repeats full recovery; no backoff or retry-load evidence.recover_entrystill takes the owner lock only for a passingjudge_owner; no new live-invalid-owner test. same-UID interference inside scratch is excluded by the approved boundary, which limits its relevance.sync_all. no durability-order regression test.pins=None; warning does not detect/repair that case or compose sources.tidy_pending.new findings
R2-P1: cancellation drops the held-result guard and permits a second save
crates/attachments/src/recovery.rs:390and:397; callercrates/attachments/src/http.rs:152.reconcile_keyremovesKeptfrom the map before awaiting repair. HTTP reconciliation runs before the detached task athttp.rs:180. if that request future is cancelled during repair,keptdrops without being reinserted, the placement guard releases, and the user's cached recovery state stays clean. the Ready record survives on disk, but subsequent live requests consult neither it nor the lost held-content guard.reproduced on dev-01: inject
publish.flushEIO socancel.jpgis public and unindexed; begin a retry; pause atresolve.sync; cancel the route future; release the blocking repair withresolve.indexEIO; upload the same bytes with a new key. response is 201,already=false, pathcancel 2.jpg; both public files exist and the original completion remains. no restart is needed. the ordinary server kill loop does not test cancellation of a reconciliation future while the process stays alive.fix: make reconciliation cancellation-safe. retain authority in the shared map through every await (with a resolving state), or use a drop guard that reinserts on cancellation, or run the whole reconciliation with its placement guard in a detached task. neither another key nor
has_kept_contentmay observe the obligation as absent until it is settled. add this exact cancellation + failed-index regression, including retry/restart convergence.R2-P2: changed-device regression never changes any completion
crates/attachments/src/tests/recovery.rs:201–216. the injectedstore.before-commitkey is rawk-dev, but the integrated store receivesaction_key("attachments.add", "k-dev"). the first upload succeeds and retires its record; the loop changingdevexecutes zero times. the assertions then replay an ordinary completed upload. this is a test regression introduced by receipt-scoping integration, despite the product fix being correct.reproduced: adding only
assert_eq!(e.markers(user), 1)immediately after the first upload fails 0 vs 1. changing the fault to the scoped key makes that assertion and the full changed-device scenario pass.fix: inject the scoped key, assert initial response failure, exactly one Ready record and zero committed events before restart; assert the record mutation count is one. keep raw-key behavior in the separate legacy-receipt test.
benchmark audit
read raw final perf-01
~/perf/out-upload-759b-ba86c6f6/,order.txt, input hashes, all 20 JSON/return-code files, fixture and harness. independently recomputed median paired head/dev ratios: 139.017948% / 119.746720% / 103.110232%, matching the PR for 4 KiB / 4 MiB / 128 MiB. all repsrc=0; ten balanced alternating pairs (odd dev→head, even head→dev); same harness and fresh fixtures. recorded hashes match the PR's head/baseline/fixture/harness hashes. the three-size comparison is fair against the explicitly pinned devd83e54db, not a measurement against later dev. median paired ratios are correctly distinguished from ratios of per-version medians.passes the ≥95% threshold for those three early-signal measurements only. does not meet the complete #771 first-PR gate. this fixture reports bytes divided by median request latency, not aggregate workload throughput, uses one client/common-root storage, and measures 200/40/5 uploads. it does not provide the required ≥60 s and ≥50 uploads/≥50 overlapping saves per point, cold/warm, split storage, 1/4 clients, 1k/10k/100k Homes, through 1 GiB, RSS/syscalls/metadata matrix. the new Rust harness is not the harness used for these measurements. initial failures are properly retained rather than erased. no benchmark rerun was needed for this audit.
independent checks and boundaries
on dev-01, reviewer worktree
~/Developer/Worktrees/review-788-r2, Nix tools and~/bin/slot,-j4:~/review788-cancellation.log).~/review788-device-red.log).~/review788-focused.log). the known failing cancellation test was explicitly skipped in this positive run.reviewer test/precondition changes are uncommitted only in that isolated VM worktree; product source is unchanged. no full-workspace or native macOS rerun claimed. process-death ordering of unsynced atomic records is consistent with the approved scope; it is not a power-loss guarantee. normal publication syncs both rename parents, but retry repair still only resyncs the destination, so it does not independently demonstrate recovery from a failed source-parent fsync. pinning now covers scoped and legacy receipts, and aged SIGKILL cases pass; that proof remains conditional on registering the pin source before any runtime opens.
fix R2-P1 and R2-P2 before round 3. close or explicitly resolve the remaining plan acceptance gaps; do not label the three-size early signal as the full performance gate.
Round 2 corrections pushed as
ef9a08d9c5c891dadd9c2f307012ee4eed1a3cdc. Ready for FINAL independent review (round 3); no merge performed.The duplicate guard is now owned by the shared held record through every repair/resolve await. Reconciliation copies the completion facts while holding placement, then removes the held record only after the engine confirms a durable result. Cancellation cannot drop the guard; the existing on-disk Ready record remains authoritative on restart. No new on-disk state, extra sync, or detached reconciliation task. One bounded completion snapshot is the only added transient cost (record cap 16 KiB); scan complexity is unchanged.
key.resolve/falsebefore the ownership fix. Test hooks compile out to the original awaits in non-test builds.All commands ran on dev-01, in
~/Developer/Worktrees/fix-759b, using Nix and~/bin/slot; heavy Cargo commands used-j4. Exact commands:Logs:
~/fix759b-r3-{red,device-red,await-red,focused,workspace,kill-loop,clippy,fmt}.log; final orchestration~/fix759b-r3-gates.logand per-gate.exitfiles. The initial await-test compilation error (private test module) was corrected before the recorded assertion-red run. The regression's global pause hook runs in an isolated child so parallel tests cannot consume it. The cancellation matrix uses task-local hooks.Gates tested the exact final source bytes as uncommitted changes atop
ba86c6f6; SHA256 of all four changed files matched between dev-01 and control before committing/pushingef9a08d9. The kill-loop's printed Git head therefore names the parent; it exercised the final changed source. Control worktree is clean. Required VM Nix shell files were not committed.Scope remains process death, not power loss. The round-2 source-parent sync, pin registration/composition and other documented limitations are not claimed resolved by this correction. No production access, deployment or merge.
Independent review, round 3 (final)
verdict: small fix (P2-or-lower only) at
ef9a08d9c5c891dadd9c2f307012ee4eed1a3cdc. the round-2 correctness fix is verified. no new P0/P1; no new P2/P3 found in this correction. overall acceptance still requires closing or explicitly resolving the previously documented acceptance gaps below. this is not approval to merge.reviewed the first PR comment, round 2 (#issuecomment-71016), fix status (#issuecomment-71096), the four-file correction, and the surrounding placement, HTTP, engine-resolution, record and store paths. control host remained read-only; all compilation/tests ran on dev-01. no code pushed.
crates/attachments/src/recovery.rs:409–421clones completion facts without removing the sharedKept. failed or cancelled repair leaves the map entry and Ready authority intact. exact cancelled-blocking-repair + index-EIO reproduction passes: refusal, one file, one Ready, zero events, then convergence.recovery.rs:284–288precede awaited engine resolution; removal at:424follows success. existing repeated sync/index-EIO regression passes. engine resolution runs owned work independently of a cancelled waiter and checks scoped/legacy receipts before committing. retry still does not resync the source parent: the existing round-2 limitation remains, so this is not proof of both-parent retry repair or power-loss durability.crates/attachments/src/tests/recovery.rs:201–236injects the scoped key and requires initial failure, one Ready, zero events and exactly one mutated record. regression passes.new findings
there is no new P0/P1 triggering kayg's round-3 stop-and-simplify rule. retain the shared-map ownership correction. before calling the complete PR ready, close or explicitly resolve the existing P2 acceptance items, especially native macOS and the complete #771 gate; the three-size early signal remains insufficient for that gate.
independent validation
isolated VM worktree:
~/Developer/Worktrees/review-788-r3, detached at the reviewed head. product code unchanged; reviewer-only additions are uncommitted incrates/attachments/src/tests/reconcile.rs, alongside required uncommitted Nix shell files. correction source and changed-device test SHA256 matched control.final run: 39 passed, zero failed, doc tests pass, exit 0. log:
~/review788-r3-focused2.log, exit file:~/review788-r3-focused2.exit. this includes all 37 shipped tests plus the two reviewer tests containing the cases above.the initial reviewer run required all 16 simultaneous uploads to succeed and correctly hit the four-upload admission limit (429). adjusted only reviewer concurrency to four, then reran successfully; initial log retained at
~/review788-r3-focused.log.also checked implementation gate exit files (workspace/kill-loop/Clippy/fmt all 0) and the recorded 1,000-round SIGKILL summary: 1,000 settled once, 19 placed-and-owing. those broader gates were not independently rerun here. the independent tests above run against the exact reviewed product source. no production access, deployment, merge or push.
Acceptance status at
0d2d416eStatus: not ready for merge. No merge was performed. This records the native runs, current partial matrix, post-round-3 small fixes, and the remaining round-1/round-2 dispositions. The complete #771 gate is still open.
Gate table
0d2d416e;cargo fmt --all --check,cargo clippy --workspace --all-targets --locked -j4 -- -D warnings, andCALTERNAL_KILL_LOOP_SEED=75931003 cargo test --workspace --locked -j4 --no-fail-fast, run through the VM slot/Nix shell. 1,289 passed, 20 ignored, 0 failed; exit 0. Log:~/fix759b-0d2d-dev-gates.log.lume@calternal-macos-01-std, attachments 38, fsio 81, engine 21 passed / 1 ignored;storage_locks5 passed. The runner held/tmp/mac-bench.lockin the same shell that installed the EXIT trap. Exit 0; the trap released it and the queuedglass-frames-795job acquired it afterward.CALTERNAL_KILL_LOOP_N=1000 CALTERNAL_KILL_LOOP_SEED=75931005 cargo test --locked -p calternal --test attachments_kill_loop -j4 -- --nocapture: 1,000 rounds / 1,000 uploads, all settled exactly once; 279 died before state, 681 in scratch, 3 placed and owing, 37 finished. Exit 0.c78fbed0aaccfbe3ba089ff6fcd31b0e2f32e4891d26fa04e6ad11789f66330e; Rust perf driver SHA256e83e22618a1ce06bc4bc42ee16ed966eff0fe4ff922c42da1cc42ae4f8700a8b. The measured product code is0f38de31; later branch commits change tests/fixtures and formatting. Baseline is release dev133cf2c2.~/bin/perf-lockon perf-01 and perf-02. Each VM has 53 JSON results at the latest status check: five upload sizes have all five valid baseline/head pairs in the first configuration, and 1 GiB is still underway. Perf-011k-split-c1: 4 KiB, 256 KiB, 4 MiB, 32 MiB pass the three thresholds; 128 MiB has response p95 116.98% and save-ack p95 116.20% of dev. Perf-0210k-ssd-c1: 4 KiB, 256 KiB, 4 MiB, and 128 MiB fail save-ack p95 (119.02%, 128.52%, 156.34%, 118.03%); 32 MiB passes. Completed throughput ratios are at least 99.03%. These are paired medians, not a complete gate result.perf/vm/upload-bench.shis only a fixed three-size wrapper; the current matrix uses the Rustcalternal-perfdriver.--cold-runs 0:sudo -n test -w /proc/sys/vm/drop_cachesis unavailable on these VMs. The current runner records RSS and response/save samples, but not metadata bytes or syscall/flush counts. The cold pairs and these system-cost measurements are not claimed.macOS behavior
The code uses
File::sync_all/fsync; it makes no explicitF_FULLFSYNCcall. The guarantee remains process death, not power-loss durability. DarwinF_SETLKowner-lock and old-flockstartup probes passed in the native suite; their semantics are not assumed identical to Linux. On APFS, case-only exclusive rename names can alias the same entry, so the fixtures account for that. The native build emitted an unusedstatevariable warning atcrates/calternal/src/storage.rs:265; it did not fail the run.Small carried-forward fixes after round 3
Commit
0f38de31adds source-parent retry sync with a recovery regression, pin-source composition and late-registration rejection tests, and idle pending-temp cleanup.6ff0490bregisters the auth-test pin source before its first store use. The workspace gate above covers these changes.Round-1 / round-2 P2 dispositions
Round-1 P3 dispositions
0f38de31and covered by the workspace suite.flocktransition: Offline stop-before-upgrade/rollback is the chosen protocol; unsupported locks fail closed and the native old-flockstartup probe passes. Live mixed-generation upgrade is not claimed.The open rows above are explicit limits, not acceptance passes. PR #788 should remain unmerged until the warm/cold matrix and the wider native/storage evidence are resolved.
Exact-head matrix continuation
The partial ratios above are from the pre-existing warm run using product binary
0f38de31; subsequent PR commits contain test/fixture and formatting changes. I prepared a fresh run at exact PR head0d2d416eon both requestedclaude@perf accounts. The dev release baseline SHA2563627d4f1a055593f4387ab2c59c4de1cfc93a6b5a6bd199ae9ac35fd1f214328matches the source on dev-01 and both perf VMs. The slot helper SHA256 is4b2c6146cf0868a8b96b49a2f3344ca2b5117d6ab905736bb9efbcea287fb423on dev-01 and both perf VMs. Exact head and driver hashes are listed above.Both fresh matrix scripts pass
bash -nand use the requested~/bin/perf-lockand~/bin/slot, with five alternating warm pairs. Transient timers are active for both VMs and fire after 7,200 seconds, after the existing three-hour capped jobs can release their locks. Each resulting service hasRuntimeMaxSec=10800andRestart=on-failurewith a 20-second delay; the script skips valid completed pairs and reruns an interrupted pair. Exact-head matrix results are not yet available, so the full gate remains open.759b matrix takeover results
Head
0d2d416e5ac13b39fb46f53e7a7af79f6d36b3b2; baseline133cf2c2. Median of matched per-pair head/dev ratios. Gates: throughput >=95%, response p95 <=105%, overlapping save-ack p95 <=105%. Only full five-pair cells can pass acceptance. RSS is retained in raw JSON, with no additional RSS gate invented.Cell counts: {'PASS': 20, 'FAIL': 18, 'partial, fails observed': 2, 'missing': 32}.
Invalid result failures (not latency gates):
job disposition and limits
Both
fix759b-exact-matrix-perf01.serviceandfix759b-exact-matrix-perf02.servicewere stopped usingsystemctl --user stop, including their service process trees. No pattern kills. perf-02 had only 3.3 GB available at takeover (below the brief's 15 GB floor); continuing measurements was not acceptable. perf-01 was still measuring useful warm data, but had >120 invocations left; each takes at least 60 seconds, plus fixture/indexing/setup, so it could not finish within the authorized approximately two-hour bound. No replacement matrix started.Collected current matrix JSON: perf-01 236 without measurement failures; perf-02 152 without measurement failures and 21 failed. All completed/failed JSON, MD and small logs were retained. Two earlier perf-01 startup failures under
pre-claude-path-invalidare separately retained, never counted. 20 fully paired cells pass; 18 fully paired cells fail; two partial cells already show failing medians; 32 cells have no matched pair. A partial cell is not an accepted five-pair result. A successful driver exit is not the paired relative performance gate.The matrix was intended to prove #771's warm upload and overlapping note-save performance on 1k/10k/100k Homes, split versus all-SSD storage, 1/4 upload clients, six upload sizes, five alternating matched pairs, at fixed seed 75931004. It does not prove the full acceptance plan: cold-cache pairs (
--cold-runs 0), metadata-byte/syscall/flush evidence, and the remaining broader native/recovery gaps remain missing. Earlier PR status is superseded by the retained table above. Most observed relative failures are save-ack p95; failed transport/HTTP runs are excluded rather than treated as passing latency samples.Results remain on each VM in
~/perf-results/759b-matrix/perf0{1,2}/resultsand~/perf-reports-kept/takeover-20261101/759b-perf0{1,2}/results; control collection:/home/kayg/perf-reports/takeover-20261101/perf0{1,2}/. Seeded Home/data/state/work cleanup is in progress separately; small reports are preserved. Both shared locks were released by these units, allowing #792 qualification to start. Verdict: incomplete and performance gates fail; not qualified, no merge.Final cleanup verification
Both 759b units stopped; quota r4 had already exited. All takeover cleanup and reproduction processes have exited. Earlier r2 cleanup completed untouched. Final free: perf-01 root 51G, split Home 58G; perf-02 root 37G, split Home 97G. Shared locks are held by #792 qualification (159697 / 1325428), not the stopped jobs. Cleanup/fixture-copy I/O overlapped the first #792 samples; those samples need overlap exclusion. Retained observations do not establish why quota-4 cache was reset.
Perf-02 cleanup and fixture-copy overlap was approximately 17:13–17:22 IST on 1 November (11:43–11:52 UTC). The earlier r2 file walk also overlapped #792 startup until it completed. #792 first overlapping samples must not be treated as uncontended measurements. No #792 process was stopped.
performance diagnosis of the 18 complete failures
Scope: the frozen table in 72886, head
0d2d416e, dev baseline133cf2c2. Recomputed all five matched ratios from retained JSON. All 18 fail save-ack p95; two also fail response p95, one also fails throughput. The other 34 partial/missing cells remain unqualified.dev comparison: these are relative head/dev budgets (throughput ≥95%, response/save p95 ≤105%), not absolute budgets dev can itself miss. The retained all-SSD regressions cannot be dismissed as “dev also fails.” The underlying flush hotspot does exist on dev. There is no demonstrated single cause for all 18.
dev-01 diagnosis: ran
1k-ssd-c4/256KiB, seed 75931004, 60s/version, four clients and 60 overlapping saves, through~/bin/slotand Nix; repeated withstrace -f -tt -T -yyfor sync/open/close/rename/locking. Reused dev133cf2c2and head0f38de31release binaries built on dev-01; head has equivalent release behavior to0d2d416e(subsequent tests/constant visibility only). The workload reproduced, the regression did not: plain dev/head save p95 49.02/38.51ms, throughput 2.561/3.295MiB/s. This shared-host single pair cannot override the perf matrix.The trace finds about four attachment-index syncs/upload on both versions (two WAL, one database, one directory). Fresh
Index::openconnections inalready_uploaded/placeclose on the hot path, causing checkpoint/close flushes despite WAL/NORMAL. Warm history-WAL sync p95 reached 125.95/75.52ms; tracing inflated save p95 to 157.30/92.87ms. This establishes inherited flush amplification/history stalls, not causal proof of the branch regression. #788 removes pending-record syncs but adds private-operation/source-parent work and changes upload completion pressure.recommendation: fix overlapping-save performance before accepting #788; retain the budgets. Start with attachment-index connection reuse/checkpoint scheduling in shared code, preferably land that fix on dev first and rebase #788; then isolate upload fairness and source-parent publication work. Preserve durability barriers. The mixed 32MiB cell and near-limit split cells need separate uncontended paired evidence. No evidence supports raising the 5% budget.
Committed diagnosis, exact commands and summaries. No perf-VM measurement, build, lock acquisition, merge or deployment; no diagnostic jobs remain running. Seeded diagnostic directories and raw traces were removed; small reports retained.
Attachment-index flush fix and measurements are in PR #831.
On current dev, the traced upload run measured 4.017 attachment-index sync calls per uploaded attachment before the fix and 1.017 after. The Linux syscall test now asserts zero index syncs for a duplicate/no-change save and one durable WAL sync for one new attachment. Dev-01 save-ack p95 moved from 56.26 ms to 40.62 ms.
On perf-01, five alternating matched pairs for the small all-SSD 1k/c4/256 KiB cell gave median save-ack p50/p95 of 11.70/18.94 ms on current dev and 12.20/18.33 ms with the fix. The median paired save-ack p95 ratio was 98.8%, within the existing 105% limit; upload response p95 ratio was 68.0% and throughput ratio 148.9%. No budgets changed. This covers one cell; the complete 18-cell matrix still needs requalification after #788 is rebased.
kayg referenced this pull request2026-11-05 23:21:11 +00:00
housekeeping #1009: rebased+failing, left open for review.
rebased private staging while preserving dev cached attachment index, request/action-key scope, legacy receipts and publication_receipts. reconciled partial move handling and retained current deploy guide plus offline upgrade notes. fixed boxed placement failures, request borrows and recovery Caller credentials; applied VM formatting. scoped Linux record-lock fixtures at module level so macOS imports stay valid. retained both legacy and action-scoped receipt pins; repaired three recovery fault injections to use dev’s scoped action keys.
head:
1ed91a0057a47ca2b125cdeef05a3f0b6cada2fe; based on devcd7f84432febfc63b788fbb9b9f9950452982d74, pushed with a recorded exact force-with-lease.frontend frozen install, check, lint, build and unit tests passed. bundle gate passed. first-paint brotli vs dev: JS 230777 B (+0 B), CSS 18386 B (+0 B).
Rust gate results (Mac VM):
cargo fmt -p calternal-attachments -p calternal-auth -p calternal -p calternal-engine -p calternal-fsio -p calternal-perf -p calternal-server -p calternal-store -- --checkcargo check -j4 --locked -p calternal --binscargo check -j4 --locked -p calternal-attachments -p calternal-auth -p calternal -p calternal-engine -p calternal-fsio -p calternal-perf -p calternal-server -p calternal-store --all-targetscargo clippy -j4 --locked -p calternal-attachments -p calternal-auth -p calternal -p calternal-engine -p calternal-fsio -p calternal-perf -p calternal-server -p calternal-store --all-targets -- -D warningscargo test -j4 --locked -p calternal-attachments -p calternal-auth -p calternal -p calternal-engine -p calternal-fsio -p calternal-perf -p calternal-server -p calternal-storecargo check -j4 --locked -p calternal-fsio -p calternal-attachments --all-targetscargo clippy -j4 --locked -p calternal-fsio -p calternal-attachments --all-targets -- -D warningscargo test -j4 --locked -p calternal-fsio -p calternal-attachments --libserver-wide all-target checks/tests are blocked on macOS by
storage_startup.rs:147borrowing Child immutably; clippy also reports unusedstateinstorage.rs:265. both reproduce on dev. component fsio/attachment check, clippy and unit tests passed after repairing action-scoped receipt pins and recovery fault keys; the earlier three recovery failures are resolved.all executed gates used the VM Nix environment, shared Mac lock and slot. exact commands, source heads, logs and dev baseline. frontend inputs are identical to the tested frontend tree when a Rust-only repair changed the head.
original-head cherry/patch inventory,
pr-788.md; unmatched entries are missing-patch candidates, with semantic overlap/replacements noted above.View command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.