Finish first-Space Composer draft transfer handoff #22
Open
opened 2026-09-14 07:10:49 +00:00 by kayg
·
25 comments
No Branch/Tag specified
dev
wave19/desktop-test
wave19/per-space-state
wave19/first-space-integration
wave19/first-space-draft-transfer
wave19/block-editor-craft
codex/wip/root-conflict-snapshot-20260914
wave12/first-space-draft-transfer
wave14/editor-overnight-combined
wave17/editor-diagnostics-3bbb
wave16/code-block-polish
wave16/image-controls
wave16/event-title-crash-control
wave16/image-preview-dispatch-repair
wave16/event-title-lifecycle-qa
wave16/editor-list-refinements
wave17/editor-layout-correction
wave16/event-edit-date
wave16/note-title-presentation
wave16/editor-final-combined
wave18/document-chrome-repair
wave17/cross-event-drop
wave16/editor-structural-combined
wave16/editor-hover-margins
wave16/editor-caret-relocation-perf
wave16/inspector-polish
wave16/image-preview-integration
wave16/english-transcription
wave16/document-background-edge
wave16/sidebar-live-layout
wave15/image-preview-ownership-repair
wave15/editor-handle-six-dot
wave15/titlebar-public-repair
wave15/sidebar-initial-restoration
wave15/editor-formatting-tooltips
wave15/editor-drag-mounted-repair
wave15/image-preview-foundation-isolated
wave15/editor-block-drag-feedback
wave15/sidebar-attachment-layout
wave14/editor-inline-plain-fastpath
wave14/editor-rendered-paste-replacement
wave14/clipboard-awaited-shutdown
wave14/editor-selectall-toolbar-perf
fix/clipboard-body-undo-group
diagnostic/clipboard-insertion-491
wave14/sidebar-unselected-drag-v2
diagnostic/sidebar-unselected-drag-trace
diagnostic/clipboard-phase-0225
wave14/sidebar-prime-access
wave14/nested-projection-handle-test-fix
wave14/sidebar-unselected-event-drag
fix/clipboard-task-ownership-6318
fix/editor-resource-url-invalidation
codex/wip/editor-handle-render-diagnostic-20260914
fix/central9c9-clipboard-crash
codex/wip/editor-handle-diagnostic-20260914
wave14/sidebar-event-runtime-repair
wave14/nested-projection-runtime-fix
wave14/sidebar-event-test-fixtures
wave14/sidebar-attachment-overlap
integration/rendered-image-clipboard
wave14/sidebar-event-preview-integration
wave14/editor-nested-list-integrate
wave14/editor-nested-list-projection
task/rendered-image-clipboard
wave14/sidebar-paste-preview-integration
wave14/sidebar-event-day-dnd
wave14/editor-preview-next
wave14/editor-list-handle-integrated
task/native-basic-paste
wave14/editor-list-keyboard-audit
task/native-clipboard-contract
codex/wip/editor-handle-geometry-20260914
wave14/editor-block-drag
wave14/editor-drag-integrated
wave14/editor-empty-marker-map-publication
wave14/editor-empty-marker-runtime-diag
wave14/editor-empty-marker-preview
wave14/editor-empty-marker-host-repro
wave14/editor-empty-marker-probe
codex/wip/editor-hr-leaf-fix-20260914
wave14/event-attachment-drop
wave14/editor-empty-marker-paint
wave14/editor-drop-list-preview
wave14/editor-finder-drop
wave14/editor-rule-caret
wave14/editor-list-enter-next
wave14/editor-image-qa
wave14/editor-mode-commands
wave13/editor-code-performance-preview
wave14/sidebar-overlap-repair
wave13/cross-day-compile-repair
wave13/spotlight-retry
wave13/editor-chrome-runtime-repair
wave13/editor-inline-fast-path
codex/wip/detached-87aa-20260914
wave12/editor-viewport-polish
wave12/craft-code-block-polish
wave12/editor-asset-return-preview
wave12/voice-polish-preview
wave12/editor-native-return-runtime-repair
wave12/editor-asset-focus
wave12/cross-day-reviewed-integration
wave12/optional-voice-provider-finish
wave12/event-move-descriptor-compile-fix
wave12/editor-image-geometry-preview
wave12/editor-native-return-undo-repair
wave12/image-native-geometry-fixture
wave12/editor-pattern-preview
wave12/editor-bullet-continuation
wave12/editor-top-chrome
wave12/voice-composer-restart
wave12/speech-variable-buffer-repair
wave12/editor-image-preview
wave12/event-move-descriptor-scale
wave12/editor-image-geometry
wave12/afternoon-ui-preview
wave12/sidebar-hosted-bounds-repair
wave12/sidebar-overlap-live
wave12/speech-e2e-verification
wave12/mentions-polish-finish
wave12/editor-structural-range-repair
wave12/sidebar-fade-desktop-preview
wave12/sidebar-design-ledger
wave12/voice-assets-physical-fixtures
wave12/native-event-marker-polish
wave12/sidebar-fade-undo-preview
wave12/event-move-fence-corrections
wave12/sidebar-fade-boundary-repair
wave12/parent-space-entry-integration
wave12/editor-undo-group-repair
wave12/native-event-row-performance
wave12/parent-swipe-integration
wave12/metadata-noteid-test-fix
wave12/space-composer-generation-fix
wave12/voice-lifecycle-clock-fixture
wave12/sidebar-child-binding
wave12/voice-provider-pool-preview
wave12/composer-recording-preview
wave12/event-cross-day-store-corrections
wave12/voice-async-test-locks
wave12/speech-buffer-lease-fix
wave12/composer-no-top-readouts
wave12/sidebar-child-target
wave12/space-required-composer
wave12/editor-correctness-preview
wave12/voice-provider-compile-corrected
wave12/event-move-integration
wave12/voice-assets-compile-fix
wave12/parakeet-compile-fix
wave12/note-metadata-flexibility
wave12/sidebar-event-drag-drop
wave12/editor-paste-source-guard
wave12/note-asset-import-safety-causal-tests
wave12/note-asset-import-safety
wave12/editor-readonly-command-guards
wave12/voice-provider-integration
wave12/editor-format-flexibility
wave12/hosted-sidebar-ui-sdk-fix
wave12/event-cross-day-store
wave12/voice-app-wiring
wave12/voice-parakeet-assets
wave12/voice-hosted-await-fix
wave12/event-edit-date-guard
wave12/event-cross-day-app
wave12/network-client-entitlement
wave12/sidebar-row-overlap
wave12/voice-settings-surface
wave12/parakeet-capture-adapter
wave12/task-marker-normalization
wave12/voice-polish-integration
wave12/voice-capture-hardening
wave12/voice-provider-settings-plan
wave12/copied-space-editor-io
wave12/hosted-background-sendability
wave12/voice-stop-nlp
wave12/voice-fixture-roots
wave12/voice-claim-collision
wave12/sidebar-add-swipe-plan
wave12/copied-space-app-wiring-plan
wave12/voice-fence-stat-compilefix
wave12/composer-dismiss-crash-hotfix
wave12/voice-retainer-defer-fix
wave12/overnight-recovery-space-preview
wave12/background-checkpoint-compilefix
wave12/copied-space-enumeration-fix
wave12/copied-space-local-state
wave12/voice-fence-fixture-fix
wave12/voice-manifest-fd-fix
wave12/voice-recovery-publication-proof
wave12/voice-retainer-bytecount-fix
wave12/overnight-navigation-background-compilefix
wave12/navigation-work-diagnostic
wave12/overnight-navigation-background-preview
wave12/background-import-bounds
wave12/overnight-voice-lifecycle-preview
wave12/voice-frozen-claim
wave12/voice-input-seam
wave12/voice-recovery-compile-fix
wave12/voice-terminal-cleanup-plan
wave12/voice-recovery-activation-plan-current
wave12/overnight-runtime-probe-preview
wave12/overnight-sandbox-startup-preview
wave12/startup-geometry-diagnostic
wave12/voice-source-sandbox-fix
wave12/image-root-sandbox-fix
wave12/perf-scroll-zero-args
wave12/overnight-document-geometry-preview
wave12/native-document-geometry-diagnostic
wave12/overnight-draft-root-preview
wave12/voice-recovery-c-session-fence
wave12/draft-root-direct-open
wave12/hosted-single-module-linkage
wave12/overnight-voice-recovery-preview
wave12/voice-recovery-checkpoint-a-finalization
wave12/copied-space-local-state-plan
wave12/overnight-refresh-hosted-preview
wave12/incremental-refresh-bounded-load
wave12/raw-source-reconciliation-test-fix
wave12/overnight-rendering-startup-preview
wave12/draft-root-diagnostic
wave12/day-event-bulk-load
wave12/speech-asset-install-test-preview
wave12/hr-material-contrast
wave12/height-clamp-followup
wave12/voice-recovery-checkpoint-a-corrections
wave12/overnight-cstore-caret-preview
wave12/voice-recovery-checkpoint-a
wave12/editor-adjacent-caret-boundary-v3
wave12/voice-recovery-index-query-fix
wave12/editor-adjacent-caret-boundary-v2
wave12/voice-recovery-index-query
wave12/startup-collector-empty-args
wave12/editor-adjacent-caret-boundary
wave12/overnight-hr-storage-preview
wave12/hr-native-diagnostic-followup
wave12/hr-native-diagnostic
wave12/overnight-storage-settings-preview
wave12/snapshot-native-move-followup
wave12/speech-local-fallback
wave12/settings-stream-test-compilefix
wave12/snapshot-path-identity-followup
wave12/corefrontmatter-join-fastpath
wave12/speech-fallback-plan
wave12/overnight-caret-control-registry
wave12/editor-registry-compilefix
wave12/voicea-test-compilefix
wave12/overnight-caret-control-ready
wave12/voicea-enum-compilefix
wave12/voice-recovery-phaseb
wave12/overnight-caret-control
wave12/overnight-polish-storage-preview
wave12/voicea-foundation-compilefix
wave12/snapshot-path-identity
wave12/overnight-native-polish-preview
wave12/hr-rule-geometry
wave12/speech-conversion-fixture
wave12/editor-deferred-caret
wave12/overnight-hosted-lifetime-preview
wave12/marker-glyph-clipping
wave12/voice-recovery-activation
wave12/overnight-package-fixture-preview
wave12/overnight-lifetime-voice-preview
wave12/app-tests-cleanup
wave12/snapshot-physical-fixtures
wave12/event-date-title-punctuation
wave12/overnight-lifetime-voice-plan
wave12/overnight-draw-before
wave12/overnight-picker-event-preview
wave12/settings-watcher
wave12/event-date-title-fix
wave12/note-background-picker-fix
wave12/editor-lifetime
wave12/overnight-draw-preview
wave12/snapshot-attribute-compile-fix
wave12/editor-accepted-draw-trace
wave12/overnight-runtime-preview
wave12/composer-test-concurrency-fix
wave12/editor-caret-performance
wave12/overnight-snapshot-correction
wave12/settings-model-callbacks
wave12/overnight-full-preview
wave12/overnight-store-preview
wave12/rendered-bullet-fix
wave12/settings-document-fixture-fix
wave12/composer-task-pill-ui
wave12/overnight-roadmap-preview
wave12/task-tag-readouts
wave12/event-snapshot-dependency
wave12/h1-strict-preview
wave12/settings-store-await-fix
wave12/settings-store-test-fix
wave12/overnight-pill-preview
wave12/composer-pill-accent-fix
wave12/composer-pill-final
wave11/sidebar-cold-index-prime
wave12/overnight-preview
wave11/voice-draft-recovery
wave11/voice-transcription-finish
wave11/note-save-rename
wave11/task-event-preview
wave11/settings-enabled-plugin-section
wave11/pill-fade-preview
wave11/sidebar-top-fade-regression
wave11/event-sidebar-preview
wave11/composer-pill-restore
wave11/settings-plugins-portability
wave11/composer-hash-semantics
wave11/event-composer-edit
wave11/sidebar-spacing-followup
wave11/editor-performance-evidence
wave11/voice-preview
wave11/voice-stop-repair
wave11/polish-verification
wave11/plugins-settings-ui
wave11/bullet-list-regression
wave11/sidebar-insert-stability
wave11/polish-preview
wave11/document-style-repair
wave11/composer-native-readouts
wave11/mentions-disclosure-motion
wave11/sidebar-swipe-compact
wave11/legacy-helper-path-fix
wave11/persistence-integration
wave11/capsule-instant-presentation
wave11/native-link-activation
wave11/desktop-integration
wave11/link-integration
wave11/synthetic-note-names
wave11/composer-overflow-actions
wave11/legacy-root-links
wave11/note-title-punctuation
wave11/note-title-metadata
wave11/spotlight-navigation
wave11/spotlight-trace-baseline
wave11/note-name-collisions
wave11/identity-query-indexes
wave11/note-heading-title
wave11/capsule-scroll-chrome
wave11/sidebar-context-menu
wave11/spotlight-metadata
wave11/rename-link-repair
wave11/analytics-native
wave11/sidebar-scroll-restoration
wave11/sidebar-bottom-spacing
wave11/capsule-optical-alignment
wave11/markdown-link-resolution
wave11/command-results-layout
wave11/capsule-outside-dismissal
wave11/events-folder
wave11/capsule-query-retention
wave11/capsule-snap-preview
wave11/composer-controls-preview
wave11/sidebar-fade-preview
wave11/selection-lookup
wave11/note-creation-routing
wave11/sidebar-header-spacing
wave11/block-editor
wave11/space-onboarding
wave11/space-terminology
wave4/voice
wave2/search
wave4/glur-probe
wave7/cli-integration
wave12/inspector-style
wave4/document-presentation
wave2/cli
wave2/sidebar
No results found.
Labels
Clear labels
No items
No 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-macos#22
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Problem
The composer needs a safe handoff when its owner moves between Spaces or is replaced while it owns unsaved text, a stopped voice recording, an event edit, or a sidebar child target. The handoff must preserve the draft, publish it to the intended destination once, and remove the old source only after exact destination evidence and source compare-and-swap checks. A mutation, stale Space/session, crash, or destination replacement must retain the current owner and leave an unrelated occupant untouched.
Candidate and status
/root/unfinished_work_comparison(read-only comparison and issue tracking)..worktrees/first-space-draft-transfer,wave12/first-space-draft-transfer.8356e0434d9dee2dfa0818ca2066f535dde8d540(WIP preserve first-space draft transfer), based ona5d71c4c.Sources/CalternalComposer/ComposerModel.swift,Sources/CalternalComposer/DraftStore.swift, andTests/CalternalComposerTests/ComposerSpaceTransferTests.swift; the branch also contains the earlier parent-target foundation inComposerParentTarget.swift.1d8f4adfhas no producer callsite for these transfer APIs.Intended user behavior
When an Add Note or Add Voice action captures an exact sidebar parent, the composer pins its Space, day, source path, identity, and SHA-256/byte-count proof.
beginParentTargetaccepts the target only for an empty, otherwise unowned composer; selection changes and relaunches cannot retarget it. The eventual submission is a parent-fenced note or voice child, so the AppModel can reread the source and perform an exact expected-data CAS before writing the child.For a Space owner handoff,
prepareSpaceTransferfirst classifies any durable legacy draft, then freezes text, mode/date, event or parent target, recording receipt, source lease, and generation fences in an opaque transfer token. The destination'spublishSpaceTransfercreates the destination only if its Space/root and existing occupant match the token; text uses an exact snapshot and voice uses receipt-bound CAF staging/retention.finishSpaceTransferrevalidates the destination proof and performs recoverable source quarantine, commit, and finalization. If the composer changes during any awaited step, the transfer invalidates and restores or persists the newer source owner. A crash or restart reconciles the durable marker. Explicit discard clears the parent and recording only after ordinary draft/asset cleanup succeeds.The current slice supplies these producer-side seams and focused tests only. It does not connect the Space switch, sidebar Add Note/Add Voice gesture, AppModel child writer, Capsule UI, or retry/discard presentation, so a user cannot reach this behavior in the current app.
Acceptance checklist
.agents/first-space-draft-transfer-lock-publication-correction-plan.md.beginParentTarget,prepareSpaceTransfer, destination publication, authorization, andfinishSpaceTransfer; add AppModel writer CAS and UI retry/discard states.agents@mbp, then VM UI coverage for the reachable handoff and child flows; record reviewer, QA, performance, and user-acceptance evidence in this issue and #20./root/unfinished_work_comparison(comparison/audit),.worktrees/first-space-draft-transfer, branchwave12/first-space-draft-transfer: status remains preserved WIP at8356e0434d9dee2dfa0818ca2066f535dde8d540. Read-only checks on 2026-09-14 found the worktree clean, the public seamsbeginParentTarget,prepareSpaceTransfer,publishSpaceTransfer,revalidateSpaceTransferPublication, andfinishSpaceTransfer, and 15 focusedComposerSpaceTransferTests(including the three WIP recovery/mutation tests).rgfound no App/Capsule/Space consumer callsite in the candidate or latest integration1d8f4adf, so the behavior is currently unreachable from the app. No build, runtime, UI, reviewer, or performance checks were run. Next action is focused review and consumer wiring; preserve the branch until that work is accepted or explicit supersession evidence is recorded.Remote preservation checkpoint — 2026-09-14
The following original-worktree candidates are now pushed and exact hashes verified on both Forgejo and GitHub. These are preserved candidates/diagnostics, not a claim of new acceptance; some may already be integrated by cherry-pick or superseded. Use the issue’s existing evidence before choosing changes to resume.
wave12/first-space-draft-transfer—8356e0434d9dee2dfa0818ca2066f535dde8d540Master #20 contains the resume instructions. No force push; dev remains
1d8f4adf.Resume checkpoint — 2026-09-14 (this session)
1d8f4adf(was84de423, 546 behind); local whitespace-only diff stashed..worktrees/first-space-draft-transfer, branchwave19/first-space-draft-transfer, created from dev and merged with preserved WIP8356e0434. Merge commitd532244.ComposerModel.swift, both resolved by combining intents:attachVoiceRecordingkeeps dev'sreplacing:CAS plus the WIP parent-target guard and pending-transcript carry (the transcript merge now uses the carried recording);makeSubmissionkeeps the WIP parent-fenced early return ahead of dev's restored-draftrehydratedEventEditTargetpath. DraftStore/ParentTarget/tests merged cleanly.swift buildof the merged tree on agents@mbp (~/Developer/Worktrees/first-space-draft-transfer) compiles; only pre-existingVoiceDraftRecovery.swifttrywarnings.ComposerSpaceTransferTests/ComposerParentTargetTestsrun on agents@mbp; read-only map of WIP seams versus App wiring points; then review and wiring plan. No review/runtime/acceptance claims yet.Review verdict — merged WIP on
wave19/first-space-draft-transfer(dev1d8f4adf+ WIP8356e043), 2026-09-14Static reviewer pass (read-only) over
ComposerModel.swift,DraftStore.swift,ComposerParentTarget.swiftand the two test files. Overall: not shippable as-is; the producer seams are sound in shape (no flock spans anawait; no DraftStore actor state touched from MainActor; transfer values areSendable), but the recovery state machine has blockers. I spot-checked findings 3 and 5 in source; both hold.Blockers / majors (file:line refer to the worktree head after the compile fixes):
DraftStore.swift:1367-1370); a stop before it loses unsaved text, a stop after it (beforefinishSpaceTransferwrites a source marker) leaves an orphan destination that a fresh source store cannot identify or abort.ComposerModel.swift:1283-1288,abandonSpaceTransfer:1219); the stale destination then collides with the next transfer deterministically.admitOrdinaryMutation(DraftStore.swift:3960-3965) rejects the owningrollbackPendingsave/delete thatrollbackInvalidatedSpaceTransferneeds, so mutation-during-cleanup rollback can never persist or acknowledge. This is the cause of the hang observed intestMutationDuringSourceCleanupRestoresUsableCAFon agents@mbp.validateDestinationAttestationreleases the destination flock before the source unlink (DraftStore.swift:4232-4255); a replacement in the gap removes the source on stale evidence with no restore branch.validateDestinationAttestation(:3535-3543, callers at 3746-3917, 4218-4618); A→B vs B→A transfers can deadlock.removeMarkerSourceCAF/removeMarkerPublicCAF/restoreMarkerSourceCAF/manifest cleanup (:3307-3323,:3509-3513).:3808-3819), leaving two owners;testQuarantinedTransferRecoversAfterNewDraftStorecurrently blesses this.:6260-6263,:183).Correction plan verdict: §1 REQUIRED (with one change: an orphan payload that is the only copy of unsaved text must be adopted, not deleted); §2 REQUIRED; §3 REQUIRED and currently broken (item 3 above); §4 DESIRABLE only, except the size-limit fix which is required.
App wiring decision: option A — replace the
ComposerModelper Space.draftStorestaysprivate let;CapsuleComposerFeature.composerbecomesvar; onvaultSessionchange the feature quiesces send/voice, recovers any stopped result into the old model, runs prepare→publish→revalidate→finish on the old model (kept installed for retry sincesourceModelIDand pending phases live on it), and only after finish succeeds constructs a destination-bound model, restores it, and installs it behind a generation fence so late voice callbacks cannot attach to the replacement.restoreDraft()on the destination model must be able to load a published transfer (currently the legacyloadrejects recovery snapshots,DraftStore.swift:1119-1128).Minimal causal test additions (replacing padding): crash after payload/before marker with unsaved-only UTF-8; crash after source intent/before destination CAS (voice); crash after destination CAS/before attestation binding (voice, fresh source store) — replaces the current expectation in
testQuarantinedTransferRecoversAfterNewDraftStore; mutation-after-publication proves exact destination abort; replacement tests assert bytes and identity intact; one writer-lock admission test; one near-limit text transfer; one inverse-root replacement race (nested-lock guard); one last-moment source CAF replacement.Next: compile-fix commit lands with the per-test matrix, then implementation is delegated in three lanes with distinct file ownership (DraftStore/ComposerModel corrections; App Space handoff; sidebar Add Note/Add Voice + AppModel parent CAS writer), each followed by a reviewer pass, then app build → VM UI checks.
Compile fix landed —
d8b4454aonwave19/first-space-draft-transfer(2026-09-14)The WIP had never compiled. Five mechanical Swift 6 fixes in
DraftStore.swift(flock symbol shadowing at :2798/:2801, nestedwithCStringclosure forrenameat:2911-2914, missingtry:2981, throwing calls inguard:4424-4433,receipt.sourceReceipt:4658).swift buildandswift build --build-testsare clean on agents@mbp;git diff --checkclean.Test matrix at
d8b4454a(agents@mbp, per-method runs with 180 s guard where the class run hung):ComposerSpaceTransferTests(15): 8 pass. Fail:testDestinationCAFReplacementBlocksCleanupAfterStaleAuthorization(NSCocoaError 4 removing a CAF that is already gone),testQuarantinedTransferRecoversAfterNewDraftStore,testStoppedCAFDoesNotOverrideUnseenLegacyText,testStoppedCAFTransfersAndSourceCleanupIsReceiptBound(allreceiptMismatch). Hang (expectation never fulfilled):testMutationDuringSourceCleanupRestoresUsableCAF,testMutationAfterCommitBeforeReturnRestoresCAFAndLatestSource,testMutationDuringFinalizationPersistsFreshOwner— matches the rollback-admission blocker in the review above.ComposerParentTargetTests: 14 run, 3 fail (testRecoveryDiscardClaimsPhaseBeforeCleanupFailureAndResumes:525,testRecoveryDiscardLeavesPendingCommitEvidenceUntouched:617/:655).ComposerModelTests: 22 run, 8 fail. Six are dev-side regressions introduced by the WIP:withTransferManifestLock(DraftStore.swift:2784) throwssourceUnavailablefor ordinary save/delete when the parent cannot be opened (testDraftStoreBoundsGrowingFileAndPreservesMalformedFile,testDraftStoreRejectsOversizedSnapshotWithoutReplacingExistingDraft,testDraftTombstoneRejectsStaleAutosave,testEventEditKeepsIdentityAcrossInFlightSuccessFailureAndRestore,testQuitKeepsAndRestoresDraft),testEmptyEventEditDraftRetainsIdentityAcrossSuspendAndRestore(CancellationError at ComposerModel.swift:2060), andtestVoiceAttachmentRefusalLeavesCAFWithCallerUntilExplicitDiscard(caller-owneddiscardVoiceRecording(_:)no longer deletes the CAF). These block any app build carrying the WIP until fixed.VoiceFrozenClaimTests: 9/9.Assignments now running (separate worktrees, to be merged onto
wave19/first-space-draft-transfer):wave19/first-space-draft-transfer: restore dev behavior first (gate: ComposerModelTests 22/22), then reviewer items 7 → 9, 8 → 1-4 → 5-6, thenrestoreDraft()of a published transfer and aspaceTransferFailure/retrySpaceTransfer()/discardSpaceTransfer()surface for the UI, then the causal test set.wave19/space-handoff-app: option A app wiring (per-SpaceComposerModelreplacement behind a generation fence; prepare→publish→revalidate→finish on the old model; native Retry/Discard affordance).wave19/parent-child-flows: sidebar Add Note / Add Voice capturing the exact event source intobeginParentTarget;AppModel.commithandling of.noteWithParent/.voiceNoteWithParentwith reread +expectedSource.matchesCAS and a newparentSourceChangederror that keeps the draft.User-facing delivery will be chunked: chunk A = Space switch with a typed draft (then voice), chunk B = Add Note / Add Voice under an event. Each chunk: reviewer → agents@mbp app build → VM cua-driver checks → single build at
kayg@mbp:~/Applications/Calternal.appfor user acceptance.Runtime evidence — chunk A (typed draft follows a Space change) on the VM, 2026-09-14
Build:
wave19/first-space-integration@ea04a2f(= Lane 118a2bbb+ Lane 3892de87+ Lane 244d4c63+ integration fixes901dbd6,9abdee9,8144203,ea04a2f), Debug app built on agents@mbp, deployed tolume@calternal-macos-vmas~/Apps/Calternal-first-space-integration.app, driven with cua-driver (unrestricted;scope: "desktop"clicks reach the sandboxed NSOpenPanel).Product fact that changed the wiring: choosing a Space in Settings does not switch live ("This space will open the next time you launch Calternal"); only first-run adoption replaces the model in-process (
MainWindowController.spaceSelected). The handoff is therefore wired at (1) next launch, from the previous Space's bookmark persisted at choose time (settings.previousVaultBookmark), before the composer's firstrestoreDraft(), and (2) first-run adoption; the livevaultSessionpath is kept.Steps and observations:
+→ typed "Draft moves with me 123" → Esc.Perf QA/.calternal/drafts/composer.json={"text":"Draft moves with me 123","mode":"event",…}.86ccc9c" → Open Space. Settings shows the new folder and the next-launch notice.86ccc9c";+shows the composer with "Draft moves with me 123"..composer-recovery.lock; Native Break drafts dir containscomposer.jsonwith the same text (byte-identical fields).(Control run beforehand: relaunching into Perf QA with no previous-Space draft restored the legacy draft unchanged.)
Hosted App tests (launchd-hosted runner
Scripts/apptests-mbp.sh, new in this branch because xcodebuild over plain ssh cannot spawn the TEST_HOST):ComposerVoiceLifecycleTests15/15,EventAttachmentDropTests13/13, including typed-draft survival across a session swap, failed publish keeping the old composer with Retry/Discard state, active recording stopped and retained across handoff, A→B→C latest-wins, launch handoff success and failure keeping the previous-Space key, parent-note exact write and byte-identical rejection after source change.Reviewer pass on the App wiring (read-only) found and the lane fixed: active capture was cancelled (CAF deleted) on handoff; cancellation was not a latest-wins fence; Discard advanced after suppressed cleanup failures.
Not yet done / gates before a
kayg@mbpbuild: Lane 1 DraftStore corrections (reviewer items 1-6, 8-9) are still in progress onwave19/first-space-draft-transfer(4f6ec94rollback-owner admission,ef5550c.calternal/drafts/voicetraversal fix that unblocked the hanging rollback test); voice transfer and crash-window recovery are unverified at runtime; no performance run; no adversarial pass. Chunk B (Add Note / Add Voice under an event) is wired and unit-tested but not yet driven on the VM.Runtime evidence — chunk B (Add Note under an exact event) on the VM, build
ea04a2f:86ccc9c":notes/parent-note-via-chunk-b-09169a8a570d49d795122193334ec60f.mdcreated (frontmatter title + H1), andevents/20260614-dailynote.md:11gained the child link- [Parent note via chunk B](<../notes/parent-note-via-chunk-b-….md>)under that event.Lane 1 corrections landed and integrated (2026-09-14, later):
wave19/first-space-draft-transfer@fac69cd(pushed): B1 newer frozen payload recovery (dcec54b), B2 post-CAS destination recheck with receipt-CAS source restore (349f2db), B3 durable rollback for bound markers on destination loss (97b849a), M1 voice metadata bound into the marker (7848a5c), M2-M5 retry/discard pre-authorization phases, no suppressed destination abort (awaitingDestinationAbort), no-replace quarantine of marker/payload, retained-voice ownership through save/suspend/send/discard (fac69cd). Build host: ComposerSpaceTransferTests 23/23 (9 causal boundary tests), ComposerParentTargetTests 14/14, ComposerModelTests 22/22, VoiceFrozenClaimTests 9/9. VoiceDraftRecoveryTests keeps 3 pre-existing dev-baseline fixture failures (:886/:892/:902, non-hex placeholder revisions).wave19/first-space-integration(pushed) with the App rewired tospaceTransferFailure/retrySpaceTransfer()/discardSpaceTransfer()(df73318). Hosted App tests 27/27..calternal/drafts/composer.jsonnow holds that text, Native Break drafts dir is empty.kayg@mbpbuild for #22 until the review says shippable and a voice-draft run passes on the VM.Worker TransferCoreGate3, worktree .worktrees/first-space-draft-transfer on wave19/first-space-draft-transfer: completed round-3 source recovery fix and six missing adversarial pins. Commits
0149f24,67e49df,f378a64,d68e89e,8dd557e,d13dd94. Final agents@mbp evidence via Scripts/build-mbp.sh: ComposerSpaceTransferTests Executed 31, 0 failures; ComposerParentTargetTests Executed 14, 0 failures; ComposerModelTests Executed 25, 0 failures; VoiceFrozenClaimTests Executed 9, 0 failures; VoiceDraftRecoveryTests Executed 40, exactly three accepted dev-baseline fixture failures at :886/:892/:902; package mode swift build completed. Next action: parent integration and project-level verification.Overnight status (2026-09-14 late):
.calternal/drafts/*between a proof and the final deletion are out of scope (surfaced, not survived). User chose text-only delivery first, voice after retained-voice handoff.wave19/first-space-draft-transfer: destination reservation (O_CREAT|O_EXCL create,.creating→.reserved→.boundhandshake, admission fence on the destination, exact-CAS consume, restart rules), lease-bound voice submissions (.eventWithVoiceLease,.voiceNoteWithParentLease, App consumes viareadVoiceBytes()—cf7664aon integration), round-6 recovery fixes (0cc0f18…e140dca: rollbackPending boundary, discard admission, foreign unbound recovery, quarantined payload restoration, voice retry identity, descriptor-bound reservation CAS).wave19/first-space-integration@b047874(round 5): hosted App tests ComposerVoiceLifecycleTests 14/14 + EventAttachmentDropTests 14/14; VM scripted handoff (Scripts/vm/space_handoff_check.py): typed draft in Perf QA → choose Native Break → relaunch → draft in Native Break, gone from Perf QA (settles a few seconds after launch).Round 6 landed (
wave19/first-space-draft-transfer@6791466, pushed; integrationwave19/first-space-integration@29d22d4, pushed):0cc0f18), reservation.creatinghandshake (9abe345), discard admission (a8501af), foreign unbound recovery (6df74a3), quarantined payload restoration (965a5f7), voice retry identity before reservation (a81eb8c), descriptor-bound reservation CAS (cd12c13), nested-flock deadlock in writer admission found via sample and fixed (3bee048), retained-voice handoff through the reservation path (64b4dba), seven pins (6791466).Scripts/vm/space_handoff_check.py, real events): typed draft in the open Space → Settings → choose another Space (Go to Folder) → relaunch → draft store moved (verified twice: Perf QA→Native Break and, by accident of a mis-click, Native Break→~/Downloads which the app scaffolded as a Space — cleaned up). Handoff completes ~60 s after launch on the VM, worth profiling..creatingreservation is aged out after 60 s so a live but slow source can lose it; voice additionally needs retained-voice crash/rollback safety and the App must restore the previous-vault composer before preparing. Round 7 in progress: flock-based liveness handshake (no timeout), retained-voice envelope on pre-marker/rollback paths, App restore-before-prepare, plus the named pins.Worker/role: TransferCoreGate7, final gate
Worktree/branch: .worktrees/first-space-integration, wave19/first-space-integration
State: implemented and committed the hosted retained-voice previous-bookmark handoff pin at
f602d2978e. The test seeds a retained recovery manifest and CAF through DraftStore's public retention API, sets settings.previousVaultBookmark, runs the launch handoff, and verifies retained destination text/voice/audio plus old manifest/CAF cleanup.Lane source checked: .worktrees/first-space-draft-transfer, wave19/first-space-draft-transfer @
9e253af309; no Lane 1 edits were made, so no merge was required.Validation evidence on agents@mbp:
The integration worktree is clean and no push was performed.
Round 7 landed (Lane 1 @
9e253af, integration @f602d29, both pushed): flock-based liveness handshake for.creatingreservations (no timeout), retained-voice envelope carried through pre-marker payload / orphan / unbound and post-CAS rollback, App restores the previous-vault composer before prepare, hosted retained previous-bookmark pin. Matrix: ComposerSpaceTransferTests 42/42, ParentTarget 15/15, ComposerModel 26/26, VoiceFrozenClaim 9/9, recovery 40 (3 accepted baseline); hosted App 29/29; BUILT_APP.Reviewer round 7 (under DECISIONS.md #19): still not shippable — one shared blocker: the reconciler releases the acquired stale creator flock before the CAS removal of the
.creatingreservation (retry can slip in between); voice additionally: post-CAS retained rollback writes through the legacy writer which rejects recovery snapshots; rollback persistence drops voice-recovery identity (no-session retry rejected / CAF orphaned after post-CAS mutation); App Discard for a failed retained previous-vault handoff uses an unbound store. Round 8 in progress for exactly those four, each with a pin.Round 8 landed (Lane 1 @
fdac714, integration @464f0cc, both pushed): owned stale creator lock held through reservation CAS/unlink + LOCK_NB creators; receipt-bound retained rollback writer; retained envelope rebound in rollback persistence; App previous-vault discard uses the bound source-store resolver under security scope and Retry/Discard are gated on an explicit previous-vault pending state. Lane 1 matrix 46/46, 15/15, 26/26, 9/9, recovery 40 (3 accepted baseline); hosted App 31/31; BUILT_APP.Reviewer round 8 (DECISIONS.md #19): text-only still blocked by two creator-lock details (a post-CAS pathname unlink that can remove a successor's live lock; missing-lock-file treated as stale without acquiring a lease); voice additionally: retained rebind must require the exact rollback baseline, absent-manifest restore must prove the CAF, transcript edits must persist. Round 9 in progress for exactly those five with pins. After it: reviewer round 9 → merge → hosted tests → VM scripted handoff (text) + seeded retained-voice VM run → adversarial pass.
Round 8 landed (Lane 1 @
fdac714, integration @464f0cc, both pushed): owned stale creator lock held through reservation CAS/unlink + LOCK_NB creators; receipt-bound retained rollback writer; retained envelope rebound in rollback persistence; App previous-vault discard uses the bound source-store resolver under security scope and Retry/Discard are gated on an explicit previous-vault pending state. Lane 1 matrix 46/46, 15/15, 26/26, 9/9, recovery 40 (3 accepted baseline); hosted App 31/31; BUILT_APP.Reviewer round 8 (DECISIONS.md #19): text-only still blocked by two creator-lock details (a post-CAS pathname unlink that can remove a successor's live lock; a missing-lock-file
.creatingreservation treated as stale without acquiring a lease); voice additionally: retained rebind must require the exact rollback baseline, absent-manifest restore must prove the CAF, transcript edits must persist. Round 9 in progress for exactly those five with pins. After it: reviewer round 9, merge, hosted tests, VM scripted handoff (text) plus a seeded retained-voice VM run, then an adversarial pass.Worker/role: TransferCoreFix12, Lane 1 implementation.
Worktree/branch: .worktrees/first-space-draft-transfer, wave19/first-space-draft-transfer.
State: T1/T2/V1/V2/V3 implemented and committed; worktree clean; no push.
Commits:
20f0036missing reservation lock lease;2815cd2close stale lock without successor pathname unlink;0ca1c5cretained manifest adoption gate;06dd22cexact rollback baseline gate;6deaab7live retained CAF requirement;522122flive CAF receipt rebinding;62000f6retained transcript persistence;39bf26freceipt binding correction;f0e6e9fmissing-lock pin;5587159retained transcript rollback pin.Validation: package build passed via Scripts/build-mbp.sh first-space-draft-transfer package. ComposerSpaceTransferTests ran per-method 46/46, each Executed 1 test with 0 failures. ComposerParentTargetTests Executed 15 tests, 0 failures. ComposerModelTests Executed 26 tests, 0 failures. VoiceFrozenClaimTests Executed 9 tests, 0 failures. VoiceDraftRecoveryTests Executed 40 tests with 3 failures only at accepted baseline assertions :886/:892/:902 (all voiceRecoveryRequiresCAS expectations); remaining 37 passed.
Next action: hand off these commits/evidence to integration; integration/main owns final merge and package matrix.
Follow-up: added deterministic T1 successor pathname pin in
4e72310(testStaleReservationProbeFencesConcurrentRetryUntilCleanup now creates a successor lock after the reservation CAS and verifies the stale descriptor close leaves it present); targeted run passed Executed 1 test, 0 failures. Final package build after this commit passed. Lane remains clean; integration should include4e72310on top of the prior round-9 commits.Final matrix update after
4e72310: ComposerSpaceTransferTests aggregate passed: Executed 46 tests, with 0 failures (0 unexpected) in 17.819 (17.823) seconds. Package build also passed after4e72310. Worktree clean.Round 9 landed (Lane 1 @
4e72310, integration @5b5f1a4, pushed). Reviewer round 9 (DECISIONS.md #19): TEXT-ONLY transfer SHIPPABLE — all cooperative-writer/crash blockers closed (creator-lock lease for missing lock files, close-only after CAS, exact rollback baseline, live-CAF proof, transcript persistence); VOICE has one remaining blocker (a recording replaced mid-transfer can get the old CAF paired with the new transcript) — round 10 in progress with pins.Evidence for the round-9 integration build: Lane 1 matrix 46/46, 15/15, 26/26, 9/9, recovery 40 (3 accepted baseline); hosted App 31/31; BUILT_APP; VM scripted handoff
Scripts/vm/space_handoff_check.py: typed draft in Native Break → Settings → Go to Folder → Overnight Perf QA → quit/relaunch →composer.jsonpresent in Perf QA with the typed text and absent from Native Break (the handoff completes ~60 s after launch on the VM; the script's settle window was widened).In flight: adversarial pass (security-reviewer) on the text path — early finding: control records (reservation, marker) are O_EXCL-created at their final name then written in place, so a crash between create and fsync leaves a zero/truncated JSON that the bounded reader classifies as unknown schema and fences the store; needs create-temp+rename or tolerate-empty-then-reclaim. Will be fixed before any delivery.
Round 10 (2026-09-15 morning): library reviewed SHIP for BOTH text and voice under DECISIONS.md #19 (reviewer round 10, no blocking findings). Lane 1
wave19/first-space-draft-transfer@94ced4d(pushed): CT-CRASH-001 fixed (initial reservation/marker via 0600 O_EXCL temp + fsync + exclusive rename + dir fsync; stale partial records reclaimed only when the creator lock is acquirable) withTransferControlRecordTests3/3; V4 retained-voice owner proof (canonical URL/bytes/duration/audio revision/inode) before any transcript borrow, plus V1/V2 negative pins. Matrix: ComposerSpaceTransferTests 49/49, ControlRecord 3/3, ParentTarget 15/15, ComposerModel 26/26, VoiceFrozenClaim 9/9, recovery 40 (3 accepted baseline).App (integration
wave19/first-space-integration):ceff4bfphase-aware Retry/Discard installed before the fallible source work (adversarial CT-UI-002), transactional bookmark pair + same-physical-root short-circuit (CT-PATH-003), retained previous-source locator kept until adoption. Currently merging Lane 1 and fixing two hosted retained-voice setup failures (cacheIneligiblewhile seeding) before the final gate; then VM text + seeded-voice runs, then a build is staged for the user.FINAL STATE for user acceptance (2026-09-15):
wave19/first-space-draft-transfer@94ced4d— reviewer round 10: SHIP for text AND voice under DECISIONS.md #19. Matrix: ComposerSpaceTransferTests 49/49, TransferControlRecordTests 3/3, ParentTarget 15/15, ComposerModel 26/26, VoiceFrozenClaim 9/9, recovery 40 (3 accepted dev-baseline fixture failures).wave19/first-space-integration@328de5d(pushed): phase-aware Retry/Discard, transactional bookmark pair, same-root short-circuit, retained previous-source locator, async test-harness teardown (the earlier hosted flakiness was the fixture unlinking the vault root before the session's background index tasks finished). Hosted App tests 33/33; Debug app builds.Scripts/vm/space_handoff_check.py): typed draft in Overnight Perf QA → Settings → Go to Folder → Native Break → quit/relaunch →composer.jsonpresent in Native Break with the typed text, absent from Perf QA. The next-launch handoff completes ~2 min after launch on the VM (index rebuild + retained-voice classification run first) — acceptable for a next-launch operation but worth profiling before merge to dev.testPreviousVaultBookmarkTransfersRetainedVoiceBeforeFirstRestoreetc.); no VM audio input, so no end-to-end voice UI run.Build staged for the user at
agents@mbp:/Users/Shared/Calternal-first-space-integration.app(revision328de5d); it will be copied tokayg@mbp:~/Applications/Calternal.apponly on the user's go-ahead. Remaining before merge to dev: user acceptance; performance profile of the launch handoff; merge ofwave19/block-editor-craftis separate (#3/#4/#24).FINAL STATE for user acceptance (2026-09-15):
wave19/first-space-draft-transfer@94ced4d— reviewer round 10: SHIP for text AND voice under DECISIONS.md #19. Matrix: ComposerSpaceTransferTests 49/49, TransferControlRecordTests 3/3, ParentTarget 15/15, ComposerModel 26/26, VoiceFrozenClaim 9/9, recovery 40 (3 accepted dev-baseline fixture failures).wave19/first-space-integration@328de5d(pushed): phase-aware Retry/Discard, transactional bookmark pair, same-root short-circuit, retained previous-source locator, async test-harness teardown (the earlier hosted flakiness was the fixture unlinking the vault root before the session's background index tasks finished). Hosted App tests 33/33; Debug app builds.Scripts/vm/space_handoff_check.py): typed draft in Overnight Perf QA → Settings → Go to Folder → Native Break → quit/relaunch →composer.jsonpresent in Native Break with the typed text, absent from Perf QA. The next-launch handoff completes ~2 min after launch on the VM (index rebuild + retained-voice classification run first) — acceptable for a next-launch operation but worth profiling before merge to dev.testPreviousVaultBookmarkTransfersRetainedVoiceBeforeFirstRestoreetc.); no VM audio input, so no end-to-end voice UI run.Build staged for the user at
agents@mbp:/Users/Shared/Calternal-first-space-integration.app(revision328de5d); it will be copied tokayg@mbp:~/Applications/Calternal.apponly on the user's go-ahead. Remaining before merge to dev: user acceptance; performance profile of the launch handoff; merge ofwave19/block-editor-craftis separate (#3/#4/#24).Decision change (2026-09-15, user): all app state is per-Space — DECISIONS.md #20. Switching Spaces leaves the composer draft in its Space and it reappears on return; there is NO cross-Space draft transfer, previous-Space bookmark, or handoff UI. This supersedes this issue's transfer premise: the transfer machinery built and hardened overnight (reservation, marker state machine, retry/discard UI, previous-bookmark launch handoff, first-run adoption transfer, ~30 transfer tests) is being REMOVED on
wave19/per-space-state(from integration328de5d).Kept from the work: exact-parent Add Note / Add Voice with SHA/byte-count CAS (
.noteWithParent/.voiceNoteWithParent[Lease],AppModel.commitParentChild); single-Space voice draft recovery hardening (phase routing on restore, receipt-bound discard, lease-bound bytes at send, CAS-save of edited restored voice, writer-admission nested-flock fix, dev regressions reversed in18a2bbb); per-SpaceComposerModel/DraftStorerebinding when the active Space changes; infra (launchd-hosted App test runner, async test-harness teardown, patched cua-driver hover, VM scripts). New VM check:Scripts/vm/per_space_draft_check.py(A→B→A, each Space keeps exactly its own draft).The staged build
328de5datkayg@mbp:~/Applications/Calternal.appstill contains the transfer; do not evaluate the transfer behavior. A replacement build follows after the cut is reviewed and verified.Per-Space cut on
wave19/per-space-state@d5b05fd(pushed). Removed: all transfer/handoff/previous-bookmark machinery (−15.4k lines). Reviewer pass found 6 issues in the new rebind path (draft text/voice lost or leaked on Space switch, racing switches, unrestored destination draft, transfer-adoption branch in attachEventEditTarget, stale analytics error) — all fixed (b8260a9,2a34cce,05b1b53) with hosted regression tests (text <300 ms before switch survives; stopped recording retained in old Space and restores there; A→B→C ends on C; late session attach binds the DraftStore). Gates: package ComposerModelTests 26/26, ParentTarget 15/15, VoiceFrozenClaim 9/9, hosted ComposerVoiceLifecycleTests 13/13 + EventAttachmentDropTests 14/14; VMScripts/vm/per_space_draft_check.py4/4 PASS (A→B→A each Space keeps exactly its own draft); Release launch on VM branch 537/575/602 ms vs dev 652/586/767 ms (app-init → first timeline draw). Second reviewer pass pending before merge to dev.Status 2026-09-16 (overnight): branch
wave19/per-space-state@ c1c8e1a (VaultIndex Swift 6.4 fix on top of 0684a52). Code complete through four reviews; package gates green (ComposerModel 26/26, ParentTarget 15/15, VoiceFrozenClaim 9/9, recovery 42 with the 3 baseline failures), VM per_space_draft_check 4/4 on 0684a52.OPEN BLOCKER: hosted
ComposerVoiceLifecycleTests/testFailedRestartRetainsLastRecordingAndAllowsAnotherAttempthangs at its very firstawait firstSession.lifecycle.waitUntilStarted()(log stops right after the test starts) — i.e. the firsttoggleRecordingis swallowed. Prime suspect: the binding fence added in 0684a52 (composerMatchesActiveSession / composerBindingsEnabled) evaluating false for the harness's 3-session setup. Diagnosis needs stderr tracing in the hosted run (log showis not permitted for the agents user). Deferred: not part of the morning build (this branch installs separately); resume after the visual lanes land.