events: identity and promotion actions (calendar step 4) #785
Closed
kayg
wants to merge 13 commits from
feat/calendar-identity into dev
pull from: feat/calendar-identity
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-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!785
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/calendar-identity"
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?
Failure → effect → detection → recovery → test: unsafe input → explicit refusal with no note writes → boundary validation → edit the note or enable the completed UI contract later → awkward YAML / hidden syntax / stored replay / cross-folder transfer regressions. Gates: fmt, four-crate clippy with -D warnings, events/notes/tasks/calternal tests on dev-01.
problem and resulting behavior
Promotion could discard authoritative journal fields; identity settlement and replay could reassign or duplicate ownership. Supported journal records now transfer as raw field bytes, and malformed or ambiguous cases refuse note writes. Production marker-writing actions stay disabled until shared editor/source/search/copy/accessibility hiding exists. The parser/describer remains enabled.
implementation plan and costs
Management reads Home bytes and promotion history; it is not a point-lookup-only operation. Nested relationship scans and source-prefix/history queries can scale poorly. Claims grow with every observed/minted/adopted address. No 100k size/latency result is claimed. Inventory line classification uses a HashSet.
failure table
round 1 implementation fixes
Head
771eb102, rebased onto #7833f94719e, which includes #781f92341a6. No merge. Production marker-writing actions are disabled until the shared UI hiding contract exists. This is backend hardening, not completed step-4 UI delivery.review_authority_moves_with_exact_types_comments_and_bytesasserts exact source/destination goldens;review_journal_authority_is_preserved_or_refusedexercises the service.review_moved_source_cannot_reclaim_live_identity,review_deleted_or_unmarked_source_refuses_reidentification; clean undo still passes.review_replay_then_new_key_cannot_create_an_owner,review_recovery_at_each_note_boundary_precedes_new_keycover stored/create/edit boundary states followed by a NEW key.review_present_unsupported_entries_refuse.review_paste_before_original_refuses_without_rekeying; pure settle returns Ambiguous. Proven bare cross-note copies can still receive fresh IDs.review_owner_import_is_adopted_before_promotion,review_copied_owner_notes_refuse_without_writes,review_ordinary_block_collision_refuses,review_observed_ordinary_ids_stay_claimed_after_removal,review_unavailable_index_never_means_free.EventsPlugin::newexposes no identify/promote actions; published action contract removes them. Backend tests use a test-only harness.review_marker_writes_are_not_exposed_before_ui_support. UI hiding itself remains unimplemented and must land before enabling writes.Red evidence on dev-01:
~/cal-r1-s4-red.log,~/cal-r1-s4-replay-red.log,~/cal-r1-s4-more-red.log,~/cal-r1-s4-retired-red.log. The new regressions were observed failing before their fixes. Boundary recovery tests simulate durable states and reopen; they are not new OS-kill tests at every boundary.Fresh gates on dev-01 in the Nix shell, heavy commands via
~/bin/slot:All passed in
~/cal-r1-s4-final2.log: events 57, notes 438 / 6 ignored, tasks 29, and calternal unit/integration checks (existing ignored cases remain ignored). The final inventory classification HashSet refactor subsequently passed fresh fmt/check, the same four-crate clippy, and~/bin/slot cargo test -p calternal-events -j4(57 passed), log~/cal-r1-s4-lookup.log. Nix flake scaffolding was not committed.Decisions and remaining limits:
events:rather than rewriting surrounding bytes.This addresses round 1. No round-2 approval, merge approval, or merge is claimed.
Independent review, round 1
Verdict: fix first. Reviewed
b30cc8a2ac04a4b7816f52eb9e692965117210f5relative to #783, after ADRs 0067/0068/0056/0066. This is a source-level review of implementation and tests, not a fresh full-suite passing claim. Inherited #781/#783 blockers also apply.P0 — Promotion deletes journal fields it does not preserve.
crates/events/src/promote.rs:241,:254,:229, and:140.carrydropstitleand empty/null fields, andchangesappends linetagsafter carriedtagsso they overwrite the authoritative entry. Example: a line- 10:00 Walk #outside ^<id>withevents.<id>.title: Private title,tags: [private], and an explicitly cleared optional field loses those values when the entire journal entry is removed. Entry comments are also removed without relocation. The existing transfer test uses the same line/entry title and no conflicting tags/nulls, so it cannot catch this. Fix: transfer the complete authority losslessly (including presence/types and retained comments), derive the owner title from that authority, and refuse unsupported transfers before any note writes. Add exact source/destination goldens with a differing title, tags, nulls, comments and unknown fields.P1 — A moved event's old source key can allocate its live ID to another line.
crates/events/src/service.rs:279,crates/events/src/claims.rs:125. Identify- 10:00 Walkin A as U; cut/paste it into B and identify B (claim holder becomes B). Type a new unmarked- 10:00 Walkin A. Its old source key still resolves to U;reservetests only A's text, bypassesfree_in_indexfor an existing source claim, and returns U although B still carries it.confirmthen assigns the holder back to A. Fix: validate existing source reservations against Home-wide live/retired ownership and provenance; distinguish crash/explicit undo recovery from a new block with coincident words. Add move-then-recreate, delete-then-recreate and outside-marker-removal ambiguity tests. Source text plus nth occurrence is not the stable block/version provenance required by O06.P1 — Startup replay does not finish ownership claims.
crates/events/src/service_promote.rs:244and:110.confirm/set_ownerhappen only infinished, after the Notes bulk job. Kill after the plan is stored or after its steps finish but beforefinished. Notes startup can complete both files whileclaims.ownerremains NULL. A subsequent promotion with a NEW key then creates a second owner for U. The existing crash test retries K first, which callsfinishedand masks the gap. Fix: make claim/owner finalization a durable replayed step or recover it before allowing new identity/promotion requests. Test restart followed by a new key, plus crash after each create/edit/finalization boundary.P1 — Unreadable/unsupported existing journal entries become “no entry.”
crates/events/src/service_promote.rs:174. A valid YAML flow recordevents: {<id>: {start: ...}}, or a blockeventsmap with a flow-map record, makespairs_atreturn None. The planner receivesentry=None, creates an owner from line clocks, and leaves the old authority untouched. The unsupported-transfer refusal only works whenSome(entry)reaches it. Fix: distinguish absent entry from present-but-unreadable/unsupported entry; refuse the latter without writes. Add real service tests for flow entries, scalar/list records and empty records, not only a pure-planner nestedsourcevalue.P1 — First-occurrence tie-breaking can give the original block a new identity.
crates/events/src/settle.rs:55andcrates/events/src/service_settle.rs:43. Copy an identified line and paste it ABOVE the original in the same note. Claims remember only the note, soHolder::Thisgives U to the first occurrence (the copy) and rekeys the original. Existing links silently target the wrong block. Fix: persist block provenance sufficient to recognize the original, or retain the ambiguity without guessing or exporting until resolved. Add paste-before-original tests, including copies with their children/owner links. The existing copy test puts duplicates in another note; it does not prove the original keeps its ID within one note.P1 — The Home-wide check does not cover adoption/ordinary blocks or existing owner notes.
crates/events/src/service_settle.rs:43,crates/events/src/service.rs:171,crates/events/src/service_promote.rs:110. An imported line carrying U with no claims row is adopted without consulting existingevent_notesor non-event blocks. An imported/copied owner note is not settled at all;has_ownerreads only claims, so an existing owner withevent-id: Ucan be followed by another newly promoted owner. Minting checks event tables only and treats index errors as free. Fix: use one authoritative Home-wide block/event claim lifecycle, consult/adopt existing owners safely, and fail closed on lookup errors. Test owner-note imports/copies and collisions with headings/ordinary linked blocks, including an unavailable index.P1 — Written markers are not hidden by the shipped editor.
crates/events/src/service.rs:419writes literal^id;packages/editor/src/syntax/hidden.ts:80has no marker decoration/atomic rule, and there is no shared client marker parser or clipboard/accessibility filtering in this stack. The Rust parser removing markers from event titles does not hide them in note/source editing. Fix: integrate the shared marker contract into editor/source/search/copy/accessibility before exposing marker-writing actions, and add corresponding UI tests (including legacy IDs and export retention). This was checked statically; no browser run is claimed.Failure-table audit:
removing_the_marker_outside_mints_a_new_idasserts SAME ID for the same words. It cannot establish matching provenance or safe behavior when an old block was deleted/moved.no_nested_linkspermitschild.len() <= 1, including zero parsed links, so it does not prove every added relationship is usable. Assert exactly one complete child link and resolved destination.expect; it does not edit after locate/before applying the bulk step. Alsosettle_noteruns before target validation and can mutate unrelated duplicate markers even when the requested target is stale.undo_is_exact_and_the_same_id_comes_backcovers a clean promotion/undo only. There is no intervening editor change in that test, no transferred journal-entry undo case, and no collapse/rekey-plus-promotion one-step undo test. Existing bulk behavior is inherited, not proof of these combinations.Mergeability: on dev-01, after fetching this exact head,
git merge-tree --write-tree origin/dev b30cc8a2exits 0 againstdev=2f304154054ec68b7855bb1f2bd24b1fb15a386d(tree0ee41bab9a1a535311a7266b1c097a25f560f1b8). Forgejo still reports false. #781 → #783 → #785 explains stacked commits, not a reproduced Git conflict. The precise Forgejo-side reason is unproven. No code pushed or merged.round 1 implementation fixes
Head
771eb102, rebased onto #7833f94719e, which includes #781f92341a6. No merge. Production marker-writing actions are disabled until the shared UI hiding contract exists. This is backend hardening, not completed step-4 UI delivery.review_authority_moves_with_exact_types_comments_and_bytesasserts exact source/destination goldens;review_journal_authority_is_preserved_or_refusedexercises the service.review_moved_source_cannot_reclaim_live_identity,review_deleted_or_unmarked_source_refuses_reidentification; clean undo still passes.review_replay_then_new_key_cannot_create_an_owner,review_recovery_at_each_note_boundary_precedes_new_keycover stored/create/edit boundary states followed by a NEW key.review_present_unsupported_entries_refuse.review_paste_before_original_refuses_without_rekeying; pure settle returns Ambiguous. Proven bare cross-note copies can still receive fresh IDs.review_owner_import_is_adopted_before_promotion,review_copied_owner_notes_refuse_without_writes,review_ordinary_block_collision_refuses,review_observed_ordinary_ids_stay_claimed_after_removal,review_unavailable_index_never_means_free.EventsPlugin::newexposes no identify/promote actions; published action contract removes them. Backend tests use a test-only harness.review_marker_writes_are_not_exposed_before_ui_support. UI hiding itself remains unimplemented and must land before enabling writes.Red evidence on dev-01:
~/cal-r1-s4-red.log,~/cal-r1-s4-replay-red.log,~/cal-r1-s4-more-red.log,~/cal-r1-s4-retired-red.log. The new regressions were observed failing before their fixes. Boundary recovery tests simulate durable states and reopen; they are not new OS-kill tests at every boundary.Fresh gates on dev-01 in the Nix shell, heavy commands via
~/bin/slot:All passed in
~/cal-r1-s4-final2.log: events 57, notes 438 / 6 ignored, tasks 29, and calternal unit/integration checks (existing ignored cases remain ignored). The final inventory classification HashSet refactor subsequently passed fresh fmt/check, the same four-crate clippy, and~/bin/slot cargo test -p calternal-events -j4(57 passed), log~/cal-r1-s4-lookup.log. Nix flake scaffolding was not committed.Decisions and remaining limits:
events:rather than rewriting surrounding bytes.This addresses round 1. No round-2 approval, merge approval, or merge is claimed.
Independent review, round 2
Verdict: fix first. Reviewed
771eb10203c86e49339d211e8f25e16ae0f2ce20relative to #783, both round-1 comments, and ADRs 0067/0068/0056/0066. No prior round-2 comment existed when checked. No code pushed or merged. Remaining #781 comment loss and #783 inline-comment visibility findings also apply.review_authority_moves_with_exact_types_comments_and_byteshas independent exact source/destination goldens. Servicereview_journal_authority_is_preserved_or_refuseddeliberately allows refusal; it proves preservation OR no writes, not successful transfer for every fixture. Neither checks relative-link targets.review_replay_then_new_key_cannot_create_an_ownerandreview_recovery_at_each_note_boundary_precedes_new_keytest NEW keys and one owner after stored/create/edit boundary simulations. These are graceful reopen/synthetic durable-state tests, not OS kills or proof claims finalize during Notes startup without a service request.review_present_unsupported_entries_refuseexercises the service, asserts refusal, unchanged source and no destination creation. Strict lookup now propagates unsupported-parent errors.review_paste_before_original_refuses_without_rekeyingchecks an above-original copy with owner-link children and unchanged whole text. It does not claim full fresh-graph copy support.review_unavailable_index_never_means_freeis a helper-level test, not a full failed-index promotion. Cold-import history remains limited as documented.review_marker_writes_are_not_exposed_before_ui_supportonly assertsEventsPlugin::new(...).actions().is_empty(). It proves the registry gate, not queued replay; see finding 2.with_writesis genuinely test-only.New P1 — Raw journal transfer changes relative-link meaning.
crates/events/src/transfer.rs:58,crates/events/src/promote.rs:172. A sourceDaily/2026/2026-10-26.mdwithevents.<U>.people: ['[Alice](<../../People/Alice.md>)']resolves Alice toPeople/Alice.md. Promotion to defaultCalendar/Walk.mddedents/copies the bytes and deletes the original record, leaving that same path on the owner; fromCalendar/it climbs outside Notes and no longer resolves. The probe observed a successful plan andSome("People/Alice.md")before versusNoneafter. Different source/destination folders can also silently retarget a link to a different existing person. Preserving raw YAML does not preserve relative semantic bindings (0068 O04). Fix: relocate recognized semantic links and their durable reference bindings together with the record, preserving unrelated bytes; refuse before any note writes when lossless rebasing is unsupported. Add source/destination fixtures at different depths and assert resolved UUID/target equality, including an occupied alternative path. This gap is in the new raw-transfer implementation; no enabled network action is claimed.New P1 — The release gate does not cover durable event-job replay.
crates/events/src/actions.rs:40,crates/notes/src/lib.rs:285,crates/notes/src/bulk/mod.rs:596and:608. Open a Home containing a queued/runningevents-identify,events-promoteorevents-settleplan from the earlier write-enabled build. Notes startup unconditionally resumes all running jobs and drives their stored Create/Edit steps, including marker insertion/rekeying, regardless of the plugin's empty action list. UI hiding is still absent. The registry-only regression never reopens with the production plugin against a pending event plan. This is a static reachability finding with the stated persisted-plan precondition, not a claim that a clean Home can dispatch the removed actions. The service's public write methods also remain ungated, although I found no other current production caller of them. Fix: put the release decision at the actual event write/replay boundary, with a durable deferred state for pending plans until UI support exists (do not discard their content/history), or complete hiding before allowing their replay. Test a stored plan and a create-completed/edit-pending plan across reopen usingEventsPlugin::new, and verify source markers cannot be written while disabled. Coordinate this explicitly with crash durability rather than silently dropping jobs.Fresh verification on dev-01, exact head above, in the Nix shell with heavy commands through
~/bin/slot:cargo test -p calternal-events review_ -j4: 17 passed, 40 filtered out.cargo test -p calternal-notes review_ -j4: 24 passed, 420 filtered out.~/bin/slot rustc --edition=2024 /tmp/cal-r2-probe.rs ... -o /tmp/cal-r2-probe, linking current cached stack libraries: observed relative-link breakage, inherited inline-comment deletion and commented relationships. Source/output on dev-01:/tmp/cal-r2-probe.rs,/tmp/cal-r2-probe.out. The inherited props/exclusion helpers are unchanged from the respective lower stack layers.No fresh full-suite, release-perf, 100k inventory or browser gate is claimed. Existing fix-status limitations remain: real process kills at the new boundaries, concurrent outside edits, intervening-edit/transferred-authority undo combinations, Home-size management cost, and complete child-link destination/reference binding. Disabling fresh actions is useful containment, but it neither completes step 4 nor makes the persisted replay path read-only.
round 2 fixes for final review
Head
eb7ffd2d, based on #783510610d6and #78194807faa. Simplification: disabled event writes are rejected at the shared bulk runner before any step, including stored-job startup replay and undo ancestry. Pending plans become durablydeferred, retaining steps, progress and receipts. Journal fields that may contain links or escaped values refuse transfer instead of guessing relative-path bindings. No merge.review_round2_cross_folder_authority_links_refuse_without_writescovers sourceDaily/2026, destinations at different depths, an occupied alternative Alice path, a same-folder local fragment and an escaped YAML link. Source text remains exact and no destination is created.bulk::drive, shared by actions, service calls and startup replay.review_round2_disabled_startup_retains_jobs_without_marker_writesreopens withEventsPlugin::newfor an entirely queued plan and a genuinely create-completed/edit-pending plan. Both retain their plan/progress/receipts, become deferred, leave source bytes unchanged and cannot bypass the gate through direct runner/service calls.review_round2_commented_owner_link_is_not_a_relationshipuses the real service and createsTasks/Planning.md; the multiline commented link is ignored. Plain-checkbox identity scanning inherits the shared visibility view.Passed on dev-01 in Nix, log
~/cal-r2-s4-final3.log:Events: 61 passed; notes: 439 passed / 6 existing ignored; tasks: 30 passed; calternal unit/integration suites passed with existing ignored tests. No build/test ran on the control host; Nix scaffolding was not committed. Pushed in #781 → #783 → #785 order.
Decisions and limits:
Ready for FINAL review round 3. This is a fix-status report, not review approval or merge authorization.
Independent review, round 3 (final)
Verdict: stop and simplify (stack blockers). Reviewed
eb7ffd2de6b470241197958459a83651879582d7, round-2 review #70969, fix status #71059, simplification notes and ADRs 0067/0068. This layer's two round-2 P1s are addressed for the reported paths; no new layer-specific P0/P1 found. The final stack still has new #781 P0 / #783 P1 findings, so it cannot be called ready or a P2-only small fix. No code pushed or merged.promote.rs:149rejects raw fields containing[,<or backslash before any bulk note writes. The service regression covers differing folder depths, an occupied alternative target, a local fragment and escaped YAML link. Exact source remains and destination is absent. This proves conservative refusal, not path rewriting.notes/src/bulk/mod.rs:305gates event jobs before any step; queued and create-completed/edit-pending reopen cases become durably deferred with exact steps/progress/results retained. Direct runner/service retry is rejected.events-identify,events-promote,events-settlejobs; all reachbulk::drive. Undo ancestry is checked, including missing/cyclic-history refusal. Production has no enable setter; the feature-gated test option defaults false and only the explicit test harness opts in. Describe/outside-import indexing reads without generating markers. No additional current marker-generation bypass found. Reopen test is for promotion, not an exhaustive dynamic test of every kind/undo history. Ordinary note imports may preserve user-supplied bytes; that is not automatic event identity allocation.Tasks/Planning.md.New inherited P0:
crates/notes/src/props.rs:291,:683: replacingm.a: old 'quoted # keepsucceeds and deletes# keep; the interior quote is plain YAML text, but the comment guard treats it as quote syntax. Independent exact-output probe reproduces both top-level and nested writes. Fix/simpler design: strict lexical write allowlist, initially rejecting any hash-bearing target and interior quotes in plain scalars; keep unsupported forms read-only and retain exact splices.New inherited P1:
crates/events/src/scan.rs:318,:321:Event::Codeenters the literal-comment helper list but not exclusion ranges. Exact input"\n10:00 hidden\n\n"is unchanged by masking and emits a false event. Fix/simpler design: one original-offset exclusion view including inline code; conservatively reject whole candidate lines intersecting excluded spans, shared by all scans.Concrete simpler delivery: keep this layer as read-only describe/index work with the existing centralized deferral gate. Do not enable identify/promote/settle or resume deferred event jobs until the smaller writer/parser contracts above and UI marker hiding land. Keep stored plans/receipts intact; do not add another identity/copy/rebasing mechanism to work around the base blockers. Linked journal transfers remain refused. This is the final stop-and-simplify decision, not a request for round 4.
Fresh dev-01 verification at this exact head, Nix shell, heavy commands via
~/bin/slot:cargo test -p calternal-events -p calternal-notes -p calternal-tasks review_ -j4passed events 21 / notes 25 / tasks 7, including both round-2 service regressions.cargo test -p calternal-notes nested_edits_match_serde_yaml -j4also passed (default 5,000 cases). Independent cached-library Rust probes nevertheless reproduce both inherited blockers. VM evidence:/tmp/cal-r3-review-tests.log,/tmp/cal-r3-property-test.log,/tmp/cal-r3-props-probe.{rs,out},/tmp/cal-r3-probe.{rs,out}.No fresh full-suite/clippy/performance/browser claim. UI hiding remains unimplemented; real process kills at all new boundaries, concurrent outside edits, broader undo combinations, cold-import provenance and Home-size performance remain the earlier documented limits. No additional new P2/P3 finding.
On hold under the three-round stop-and-simplify rule. The replacement plan is PR #802: #802
Plan: https://git.kayg.org/kayg/calternal/src/branch/docs/calendar-backend-v2-plan/docs/plans/0067-calendar-backend-v2.md
No further patches or fourth review round on this stack. The plan chooses a strict whole-frontmatter write allowlist, the editor's Lezer parser with an explicit backend bridge feasibility gate, and centralized marker writes disabled until full UI hiding. It lists salvage, independent tests and smaller replacement PRs. This comment changes no implementation code and requests no merge.
kayg referenced this pull request2026-11-05 23:21:11 +00:00
housekeeping #1009: needs-decision.
Calendar v1 identity/promotion action slice was held after review; #802 gates writes on the shared note executor. Do not replay the old executor/action model.
original head:
eb7ffd2de6b470241197958459a83651879582d7. against devcd7f84432febfc63b788fbb9b9f9950452982d74, git cherry reports 44 unmatched and 0 equivalent patches. the landing audit lists each candidate missing commit and stable patch match inpr-785.md; unmatched patches can include superseded behavior.left open, source branch unchanged. no rebase or new test claim for this decision lane.
Superseded by calendar backend v2 (#802/#803). The branch and original tips are archived under
archive/(see #1009), so nothing is lost; useful regression vectors are noted there for the active lanes. Closing.Pull request closed