feat(notes): shared note-write executor, default-off slice 0 #809
Closed
kayg
wants to merge 0 commits from
feat/note-write-executor into dev
pull from: feat/note-write-executor
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:fix/private-staging-759b-r2
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!809
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/note-write-executor"
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 1 update: pushed
f30b760afdac1de32973a7c74f3bf78c472c099c. P1/P2 addressed; fmt and clippy passed; executor 28/28; full notes 471 passed, 0 failed, 6 existing ignored. Independent re-review pending. Never merged.Round 1 implementation plan: retain full-image journal hashes and verify every participant against them; require directional placement evidence before accepting an already-applied goal; persist outside edits as
Conflicted, retaining the plan and displaced files with no undo; derive note and record staging names from the journal identity and clean them on recovery and terminal paths. No production callsites change.Costs remain O(J + K × (N + W)) recovery/placement, with O(J + N + W) memory. Each image remains bounded by the existing admission caps; staging bytes are included in journal usage. Creation evidence additionally checks the retained/public inode identity because a staged post-image alone does not prove creation.
Gates: VM-only Nix fmt check, locked clippy with
-D warnings, locked executor tests and full notes tests, all heavy commands through~/bin/slot. Never merge.Shared note-write executor, slice 0
Plan: add the isolated
calternal-notes::write_executorbyte transaction boundary,then exercise independent byte properties, real process crashes, recovery, strict
own-author undo and compaction. References: #808 at
5be50361,#802 at
6a4289fa.No production caller, Home room, task, calendar, legacy replay or publication route
is switched. There is no runtime enable switch. This is the byte protocol slice,
not approval to port actions or a claim that the complete executor-first delivery
(room isolation, semantic validation, private-state/outbox adapters) is complete.
Those participants must refuse here instead of pretending they were committed.
Costs: pure sorted-splice verification/application is O(N + W + S). Admission
and recovery load the retained journal, O(J). Placement deliberately rechecks all
participants before and after each file: worst-case O(K × (N + W) + J), plus K
file/directory syncs; memory O(N + W + J), with JSON/image copies counted. This
conservative implementation does not claim the plan's linear placement target or
any latency pass. No Home walk. Image/splice payloads are bounded before PREPARE:
1,024 participant/dependency paths, 64 MiB pre/post/dependency images, 4,096 total
forward + inverse splices and 4 MiB encoded metadata. Journal accounting includes
encoded records, abandoned private record temporaries and retained placement
files. Admission reserves space under a 1 GiB cap and refuses rather than deleting
pinned evidence. Pending/conflicted plans are always roots. Caller-released terminal
history payloads compact atomically; operation digests, author, Home, consumed undo
ancestry and displaced inodes remain. Compaction also removes unreferenced private
record temporaries. Displaced inode collection needs a later reviewed retention
protocol; it is deliberately unavailable, so those bytes can cause backpressure.
Conservative policy points implement the recommendations, not answers on kayg's
behalf: Q1
exact_undo; Q2recorded_inverse_only; Q3success_after_commit;Q4
conflict_without_replan; Q5refuse_unsupported_participants; Q6refuse_oversized_action. Explicit adaptive Trash Restore is a later planner.Placement feasibility is gated separately on each supported platform. This slice
uses exclusive create and retained atomic exchange on Linux/Apple; unsupported
platforms refuse. No route is enabled by passing Linux tests. Partial raw files
can be observed by outside editors. The private receipt boundary is not yet an
integrated Calternal generation/publication barrier. Uncooperative namespace
mutation and in-place writers prevent claiming portable filesystem CAS.
Validation on dev-01 through Nix and
~/bin/slot:cargo clippy -j4 -p calternal-notes --all-targets -- -D warnings: passed.cargo test -j4 -p calternal-notes: 467 passed, 0 failed, 6 existing ignored;doc tests passed. Includes 24 executor tests, independent generated byte models,
real subprocess kills at partial journal write/file fsync/rename/directory sync,
each note placement, COMMIT, inverse, rollback and compaction boundaries, plus
simulated ENOSPC errors at protocol boundaries. Real power-loss/filesystem fault
injection is not claimed. Initial stub runs demonstrated expected test failures.
cargo fmt --all -- --check: passed on the VM.size/protocol fixtures, not task planner/relationship/semantic compatibility proof.
NoteWriteExecutor.No Home/service/room/task/calendar/legacy replay caller changed. Production
writes remain on their existing paths; this slice freezes no existing workflow.
The six ignored tests are repository timing/manual stress gates. No Apple gate,
shared semantic writer/parser integration, ranks/claims/bindings/outbox or room
publication proof is claimed. All corresponding plan requirements refuse; later
ports remain blocked on those integrations and platform/performance gates.
Final reproducible VM commands (Nix, dev-01):
Full notes gate log:
~/note-executor-gates4.log; final locked-module gate log:~/note-executor-final.log(passed: fmt check, locked clippy, 24/24 executor tests). Never merged; no action port or production enablement.Pre-review head:
64c3983f9b3bac857c083ecd638df3b100ca9b7d. Full notes: 467 passed, 0 failed, 6 existing ignored. Final locked executor run: 24 passed, 0 failed. fmt check and clippy-D warningspassed. Local tree clean, pushed head matches origin. Independent PR review is still pending; no merge.WIP: shared note-write executor, default-off slice 0to feat(notes): shared note-write executor, default-off slice 0Independent review, round 1
Reviewed head
64c3983f9b3bac857c083ecd638df3b100ca9b7d, including admission, placement, forward recovery, rollback, committed-only undo, journal loading/compaction and the generated/crash tests. Scope is the disconnected byte executor; later room/publication/private-state integration and Apple/performance gates remain deferred as described in the PR.Verdict: fix first. P0: none. Findings:
P1: a matching post-image is treated as proof of an applied change
Location:
crates/notes/src/write_executor/recovery.rs:111(also the permissive pre/post check at lines 66–77).Scenario: Kill the existing crash-test child at
JournalDurable, before staging or placing either note. An outside editor changes onlya.mdfrom its pre-image to the exact planned post-image. On restart,checkaccepts that image even though both recorded placement-evidence paths for this note are absent;finishskips the note, appliesb.md, and records COMMIT. Undo now changesa.mdback to the pre-image, reversing an outside change the executor never applied. The same goal-only shortcut is used by initial execution and rollback. Exact bytes establish content equality, but do not establish placement provenance.Evidence: Reproduced on dev-01 against this head's compiled library and existing crash-test child, using a two-note
old -> NEWplan. Output:The reproduction asserted both evidence paths were absent before undo.
Fix: Classify each participant using its directional placement evidence as well as its public bytes. An unplaced participant must still match the directional source; accepting an already placed goal must require evidence proving that placement, including the create/delete cases. Retain ambiguous states as conflicts, and ensure rollback only reverses proven applied placements. Add regressions for an outside exact-post edit after PREPARE/before placement, after restart, and before rollback; prove such edits cannot become undoable executor work.
P2: interrupted staging leaves bytes outside journal accounting and collection
Location:
crates/notes/src/write_executor/placement.rs:85; accounting atjournal.rs:192, collection atjournal.rs:222.Scenario:
Prepared::newcreates a separate, uniquely named fsio temporary beside the deterministic evidence path, then writes and fsyncs it beforeplace. A process exit during that write, or after its fsync but before placement, leaves that temporary behind because Drop does not run. The WAL records only the deterministic evidence paths.usagecounts those paths and private-journal files;compactonly collects private record temporaries. Neither visits the abandoned staging temporary in the notes directory. Repeated interrupted recovery attempts can therefore accumulate unaccounted note images despite the stated 1 GiB budget.Fix: Give intermediate staging files a journal-owned lifecycle: record/derive and account for their identities, and safely collect abandoned intermediates without collecting displaced outside inodes or unrelated fsio files. Cover interruption inside staging write, file fsync and placement, then repeated recovery and compaction. The current
Staged(i)hook runs after the entirePrepared::new(...).place(...)call, so it does not exercise these windows.Validation: on dev-01, through Nix and the slot wrapper,
~/bin/slot cargo test --locked -j4 -p calternal-notes write_executor --libpassed 24/24. The focused P1 reproduction above also completed with its assertions passing; it demonstrates a missing regression despite the green suite. No build/test ran on the control host and no repository files were changed.The properties are genuinely generated and do execute two-note do/undo plans, although both participants receive the same generated replacement and the operation topology is fixed. The six conservative policies are named separately; no answer to the pending policy questions is inferred here. Journal version/checksum checks and terminal-only payload compaction are present. These observations do not resolve the placement-provenance and staging-lifecycle findings above.
Implementation response, round 1 of 3
Head:
f30b760afdac1de32973a7c74f3bf78c472c099c(pushed). Never merged.JournalDurable, then outside exact-post write; regression failed on the reviewed implementation and now passesConflicted, no replay/rollback/undo; plan and displaced evidence retained through repeated recovery/compaction; new undo checks every committed post-image hash-D warningsExact commands on dev-01, in the existing worktree through
nix develop -c bash -c:Logs:
~/note-executor-r1-red.log(expected pre-fix regression failure),~/note-executor-r1-gates.log(executor and full notes gates),~/note-executor-r1-final.log(final fmt/clippy). All builds/tests ran on the VM; none on the control host.Decisions: exact post bytes alone do not establish placement provenance. Replacement/deletion require retained source evidence; creation requires the retained/public inode identity as well as exact bytes. Conflicted actions remain in the existing
pendingreport list and are also reported separately inconflicted. Disposable staging is collected; retained displaced evidence is not.Open limits: no production caller enabled; existing Apple, room/publication, namespace/in-place writer and power-loss limitations remain. The six ignored tests remain existing manual/timing gates. Independent re-review is pending; this comment does not claim approval.
Independent review, round 2
Reviewed
f30b760afdac1de32973a7c74f3bf78c472c099c, focusing on the round 1 fixes, directional recovery, conflict retention, journal accounting and strict undo. Scope remains the disconnected byte executor; this does not approve production enablement or the deferred platform/publication integrations.Verdict: ready. No new P0, P1 or P2 findings. One nonblocking P3 documentation finding below.
outside_post_image_without_placement_is_never_undoablekills after durable PREPARE, asserts all evidence paths are absent, writes the exact outside post-image, and verifies no commit/undo, unchanged second note, and durable conflict through repeated recovery and compaction. It covers forward recovery and rollback. Separate initial-execution and create/delete regressions cover those paths, including staged creation without public inode identity.interrupted_staging_is_collected_on_recoverykills during partial/full staging writes, file sync, staging publication and public placement; repeated recovery checks note/private staging cleanup. The forward/inverse/rollback crash suites also check cleanup. Accounting now includes deterministic note intermediates; retained displaced evidence remains separate.Additional checks:
RecoveryReport.conflictedexplicitly surfaces conflicts, also retaining them inpending. Recovery skips durable conflicts; execute with the same key returns pending without replay; rollback and undo reject them.records()exposes the durable state. New keys require a freshly verified plan.strict_undo_refuses_entire_inverse_after_later_editchanges the second note and proves the first note remains unchanged with no inverse journal record. Same-key retries of an already committed undo return its receipt without writing again.P3: document the hash equality assumption
Location:
crates/notes/src/write_executor/journal.rs:46,recovery.rs:82–111, anddocs/implementation/note-write-executor.md:76.Recovery uses full-length BLAKE3 digest equality to classify public content, but the protocol documentation does not state the collision assumption. Document that distinct contents are assumed not to share a 256-bit BLAKE3 digest, that these checks are integrity checks rather than journal authentication, and that content equality still requires the separate placement evidence before accepting an applied goal. This is a documentation gap, not a demonstrated collision or a blocker. No collision test is requested.
Validation: independently reran on dev-01 at the reviewed SHA, via Nix and the slot wrapper:
Result: 28 passed, 0 failed, 449 filtered out. Also inspected the existing full-notes gate log (471 passed, 0 failed, 6 ignored) and final clippy log; those were not independently rerun in this round. No builds/tests ran on the control host. No code changed or pushed.
ADR 0003 evidence migration:
docs/implementation/note-write-executor.mdSource commit: 98eff7e4bd71c576e8cd3580bfa890d37f3a828f; snapshot from dev
55f35fcd. Full original source preserved below before repository removal/stripping. Design, code and test inputs are retained where applicable.Closing: head
f30b760ais already in dev (reached via43a7f740); nothing left to merge. Branch kept.Pull request closed