Finish first-Space Composer draft transfer handoff #22

Open
opened 2026-09-14 07:10:49 +00:00 by kayg · 25 comments
Owner

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

  • Worker/role: /root/unfinished_work_comparison (read-only comparison and issue tracking).
  • Worktree/branch: .worktrees/first-space-draft-transfer, wave12/first-space-draft-transfer.
  • Preserved WIP: 8356e0434d9dee2dfa0818ca2066f535dde8d540 (WIP preserve first-space draft transfer), based on a5d71c4c.
  • Scope: Sources/CalternalComposer/ComposerModel.swift, Sources/CalternalComposer/DraftStore.swift, and Tests/CalternalComposerTests/ComposerSpaceTransferTests.swift; the branch also contains the earlier parent-target foundation in ComposerParentTarget.swift.
  • State: the checkout was dirty during cleanup and is now preserved as a WIP checkpoint. The candidate is unreviewed, unbuilt, not runtime-verified, not wired into App/Capsule/sidebar UI, and not user accepted. The latest integration 1d8f4adf has no producer callsite for these transfer APIs.
  • Related records: master #20 and cleanup #19.

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. beginParentTarget accepts 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, prepareSpaceTransfer first 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's publishSpaceTransfer creates 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. finishSpaceTransfer revalidates 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

  • Review the three WIP files for Swift 6 actor, descriptor-lock, recovery, and ownership correctness; resolve the proposed correction plan at .agents/first-space-draft-transfer-lock-publication-correction-plan.md.
  • Wire Space-owner handoff and exact sidebar Add Note/Add Voice capture through beginParentTarget, prepareSpaceTransfer, destination publication, authorization, and finishSpaceTransfer; add AppModel writer CAS and UI retry/discard states.
  • Prove the parent source path, Space, day, identity, hash, and byte count stay exact; matching note/voice submissions write under that parent, while stale or conflicting sources fail closed and retain the draft.
  • Run the existing 15 focused transfer tests plus causal coverage for snapshot-before-marker crash, destination-CAS/restart recovery, source and destination manifest/CAF replacement, production save/delete lock admission, near-limit UTF-8 marker bounds, and no nested-lock deadlock.
  • Run central Swift 6 build and relevant unit/Release checks on 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.
  • Keep open until the wired behavior is reviewed, built, runtime-verified, and user accepted; otherwise mark the candidate superseded with evidence rather than deleting the preserved branch.
## 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 - Worker/role: `/root/unfinished_work_comparison` (read-only comparison and issue tracking). - Worktree/branch: `.worktrees/first-space-draft-transfer`, `wave12/first-space-draft-transfer`. - Preserved WIP: `8356e0434d9dee2dfa0818ca2066f535dde8d540` (`WIP preserve first-space draft transfer`), based on `a5d71c4c`. - Scope: `Sources/CalternalComposer/ComposerModel.swift`, `Sources/CalternalComposer/DraftStore.swift`, and `Tests/CalternalComposerTests/ComposerSpaceTransferTests.swift`; the branch also contains the earlier parent-target foundation in `ComposerParentTarget.swift`. - State: the checkout was dirty during cleanup and is now preserved as a WIP checkpoint. The candidate is unreviewed, unbuilt, not runtime-verified, not wired into App/Capsule/sidebar UI, and not user accepted. The latest integration `1d8f4adf` has no producer callsite for these transfer APIs. - Related records: master [#20](https://git.kayg.org/kayg/calternal/issues/20) and cleanup [#19](https://git.kayg.org/kayg/calternal/issues/19). ## 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. `beginParentTarget` accepts 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, `prepareSpaceTransfer` first 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's `publishSpaceTransfer` creates 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. `finishSpaceTransfer` revalidates 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 - [ ] Review the three WIP files for Swift 6 actor, descriptor-lock, recovery, and ownership correctness; resolve the proposed correction plan at `.agents/first-space-draft-transfer-lock-publication-correction-plan.md`. - [ ] Wire Space-owner handoff and exact sidebar Add Note/Add Voice capture through `beginParentTarget`, `prepareSpaceTransfer`, destination publication, authorization, and `finishSpaceTransfer`; add AppModel writer CAS and UI retry/discard states. - [ ] Prove the parent source path, Space, day, identity, hash, and byte count stay exact; matching note/voice submissions write under that parent, while stale or conflicting sources fail closed and retain the draft. - [ ] Run the existing 15 focused transfer tests plus causal coverage for snapshot-before-marker crash, destination-CAS/restart recovery, source and destination manifest/CAF replacement, production save/delete lock admission, near-limit UTF-8 marker bounds, and no nested-lock deadlock. - [ ] Run central Swift 6 build and relevant unit/Release checks on `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. - [ ] Keep open until the wired behavior is reviewed, built, runtime-verified, and user accepted; otherwise mark the candidate superseded with evidence rather than deleting the preserved branch.
Author
Owner

/root/unfinished_work_comparison (comparison/audit), .worktrees/first-space-draft-transfer, branch wave12/first-space-draft-transfer: status remains preserved WIP at 8356e0434d9dee2dfa0818ca2066f535dde8d540. Read-only checks on 2026-09-14 found the worktree clean, the public seams beginParentTarget, prepareSpaceTransfer, publishSpaceTransfer, revalidateSpaceTransferPublication, and finishSpaceTransfer, and 15 focused ComposerSpaceTransferTests (including the three WIP recovery/mutation tests). rg found no App/Capsule/Space consumer callsite in the candidate or latest integration 1d8f4adf, 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.

`/root/unfinished_work_comparison` (comparison/audit), `.worktrees/first-space-draft-transfer`, branch `wave12/first-space-draft-transfer`: status remains preserved WIP at `8356e0434d9dee2dfa0818ca2066f535dde8d540`. Read-only checks on 2026-09-14 found the worktree clean, the public seams `beginParentTarget`, `prepareSpaceTransfer`, `publishSpaceTransfer`, `revalidateSpaceTransferPublication`, and `finishSpaceTransfer`, and 15 focused `ComposerSpaceTransferTests` (including the three WIP recovery/mutation tests). `rg` found no App/Capsule/Space consumer callsite in the candidate or latest integration `1d8f4adf`, 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.
Author
Owner

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 — 8356e0434d9dee2dfa0818ca2066f535dde8d540

Master #20 contains the resume instructions. No force push; dev remains 1d8f4adf.

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` — `8356e0434d9dee2dfa0818ca2066f535dde8d540` Master #20 contains the resume instructions. No force push; dev remains 1d8f4adf.
Author
Owner

Resume checkpoint — 2026-09-14 (this session)

  • Local root checkout fast-forwarded to dev 1d8f4adf (was 84de423, 546 behind); local whitespace-only diff stashed.
  • New integration worktree .worktrees/first-space-draft-transfer, branch wave19/first-space-draft-transfer, created from dev and merged with preserved WIP 8356e0434. Merge commit d532244.
  • Two conflicts in ComposerModel.swift, both resolved by combining intents: attachVoiceRecording keeps dev's replacing: CAS plus the WIP parent-target guard and pending-transcript carry (the transcript merge now uses the carried recording); makeSubmission keeps the WIP parent-fenced early return ahead of dev's restored-draft rehydratedEventEditTarget path. DraftStore/ParentTarget/tests merged cleanly.
  • swift build of the merged tree on agents@mbp (~/Developer/Worktrees/first-space-draft-transfer) compiles; only pre-existing VoiceDraftRecovery.swift try warnings.
  • Next: focused ComposerSpaceTransferTests/ComposerParentTargetTests run on agents@mbp; read-only map of WIP seams versus App wiring points; then review and wiring plan. No review/runtime/acceptance claims yet.
Resume checkpoint — 2026-09-14 (this session) - Local root checkout fast-forwarded to dev `1d8f4adf` (was 84de423, 546 behind); local whitespace-only diff stashed. - New integration worktree `.worktrees/first-space-draft-transfer`, branch `wave19/first-space-draft-transfer`, created from dev and merged with preserved WIP `8356e0434`. Merge commit `d532244`. - Two conflicts in `ComposerModel.swift`, both resolved by combining intents: `attachVoiceRecording` keeps dev's `replacing:` CAS plus the WIP parent-target guard and pending-transcript carry (the transcript merge now uses the carried recording); `makeSubmission` keeps the WIP parent-fenced early return ahead of dev's restored-draft `rehydratedEventEditTarget` path. DraftStore/ParentTarget/tests merged cleanly. - `swift build` of the merged tree on agents@mbp (`~/Developer/Worktrees/first-space-draft-transfer`) compiles; only pre-existing `VoiceDraftRecovery.swift` `try` warnings. - Next: focused `ComposerSpaceTransferTests`/`ComposerParentTargetTests` run on agents@mbp; read-only map of WIP seams versus App wiring points; then review and wiring plan. No review/runtime/acceptance claims yet.
Author
Owner

Review verdict — merged WIP on wave19/first-space-draft-transfer (dev 1d8f4adf + WIP 8356e043), 2026-09-14

Static reviewer pass (read-only) over ComposerModel.swift, DraftStore.swift, ComposerParentTarget.swift and the two test files. Overall: not shippable as-is; the producer seams are sound in shape (no flock spans an await; no DraftStore actor state touched from MainActor; transfer values are Sendable), 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):

  1. Frozen in-memory snapshot is first made durable by the destination CAS (DraftStore.swift:1367-1370); a stop before it loses unsaved text, a stop after it (before finishSpaceTransfer writes a source marker) leaves an orphan destination that a fresh source store cannot identify or abort.
  2. Source invalidation after publication never aborts the exact destination (ComposerModel.swift:1283-1288, abandonSpaceTransfer :1219); the stale destination then collides with the next transfer deterministically.
  3. admitOrdinaryMutation (DraftStore.swift:3960-3965) rejects the owning rollbackPending save/delete that rollbackInvalidatedSpaceTransfer needs, so mutation-during-cleanup rollback can never persist or acknowledge. This is the cause of the hang observed in testMutationDuringSourceCleanupRestoresUsableCAF on agents@mbp.
  4. validateDestinationAttestation releases 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.
  5. Nested source→destination flocks in validateDestinationAttestation (:3535-3543, callers at 3746-3917, 4218-4618); A→B vs B→A transfers can deadlock.
  6. Check-then-unlink by name in removeMarkerSourceCAF/removeMarkerPublicCAF/restoreMarkerSourceCAF/manifest cleanup (:3307-3323, :3509-3513).
  7. Quarantined-voice restart recovery restores the source and drops the marker without validating/aborting the destination (:3808-3819), leaving two owners; testQuarantinedTransferRecoversAfterNewDraftStore currently blesses this.
  8. Transfer publication caps snapshots at the 256 KiB voice-recovery limit instead of the ~22 MiB legacy contract (: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 ComposerModel per Space. draftStore stays private let; CapsuleComposerFeature.composer becomes var; on vaultSession change 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 since sourceModelID and 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 legacy load rejects 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.

Review verdict — merged WIP on `wave19/first-space-draft-transfer` (dev `1d8f4adf` + WIP `8356e043`), 2026-09-14 Static reviewer pass (read-only) over `ComposerModel.swift`, `DraftStore.swift`, `ComposerParentTarget.swift` and the two test files. Overall: **not shippable as-is**; the producer seams are sound in shape (no flock spans an `await`; no DraftStore actor state touched from MainActor; transfer values are `Sendable`), 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): 1. Frozen in-memory snapshot is first made durable by the destination CAS (`DraftStore.swift:1367-1370`); a stop before it loses unsaved text, a stop after it (before `finishSpaceTransfer` writes a source marker) leaves an orphan destination that a fresh source store cannot identify or abort. 2. Source invalidation after publication never aborts the exact destination (`ComposerModel.swift:1283-1288`, `abandonSpaceTransfer` :1219); the stale destination then collides with the next transfer deterministically. 3. `admitOrdinaryMutation` (`DraftStore.swift:3960-3965`) rejects the owning `rollbackPending` save/delete that `rollbackInvalidatedSpaceTransfer` needs, so mutation-during-cleanup rollback can never persist or acknowledge. This is the cause of the hang observed in `testMutationDuringSourceCleanupRestoresUsableCAF` on agents@mbp. 4. `validateDestinationAttestation` releases 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. 5. Nested source→destination flocks in `validateDestinationAttestation` (`:3535-3543`, callers at 3746-3917, 4218-4618); A→B vs B→A transfers can deadlock. 6. Check-then-unlink by name in `removeMarkerSourceCAF`/`removeMarkerPublicCAF`/`restoreMarkerSourceCAF`/manifest cleanup (`:3307-3323`, `:3509-3513`). 7. Quarantined-voice restart recovery restores the source and drops the marker without validating/aborting the destination (`:3808-3819`), leaving two owners; `testQuarantinedTransferRecoversAfterNewDraftStore` currently blesses this. 8. Transfer publication caps snapshots at the 256 KiB voice-recovery limit instead of the ~22 MiB legacy contract (`: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 `ComposerModel` per Space.** `draftStore` stays `private let`; `CapsuleComposerFeature.composer` becomes `var`; on `vaultSession` change 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 since `sourceModelID` and 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 legacy `load` rejects 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.
Author
Owner

Compile fix landed — d8b4454a on wave19/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, nested withCString closure for renameat :2911-2914, missing try :2981, throwing calls in guard :4424-4433, receipt.sourceReceipt :4658). swift build and swift build --build-tests are clean on agents@mbp; git diff --check clean.

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 (all receiptMismatch). 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) throws sourceUnavailable for ordinary save/delete when the parent cannot be opened (testDraftStoreBoundsGrowingFileAndPreservesMalformedFile, testDraftStoreRejectsOversizedSnapshotWithoutReplacingExistingDraft, testDraftTombstoneRejectsStaleAutosave, testEventEditKeepsIdentityAcrossInFlightSuccessFailureAndRestore, testQuitKeepsAndRestoresDraft), testEmptyEventEditDraftRetainsIdentityAcrossSuspendAndRestore (CancellationError at ComposerModel.swift:2060), and testVoiceAttachmentRefusalLeavesCAFWithCallerUntilExplicitDiscard (caller-owned discardVoiceRecording(_:) 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):

  • Lane 1 wave19/first-space-draft-transfer: restore dev behavior first (gate: ComposerModelTests 22/22), then reviewer items 7 → 9, 8 → 1-4 → 5-6, then restoreDraft() of a published transfer and a spaceTransferFailure/retrySpaceTransfer()/discardSpaceTransfer() surface for the UI, then the causal test set.
  • Lane 2 wave19/space-handoff-app: option A app wiring (per-Space ComposerModel replacement behind a generation fence; prepare→publish→revalidate→finish on the old model; native Retry/Discard affordance).
  • Lane 3 wave19/parent-child-flows: sidebar Add Note / Add Voice capturing the exact event source into beginParentTarget; AppModel.commit handling of .noteWithParent/.voiceNoteWithParent with reread + expectedSource.matches CAS and a new parentSourceChanged error 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.app for user acceptance.

Compile fix landed — `d8b4454a` on `wave19/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, nested `withCString` closure for `renameat` :2911-2914, missing `try` :2981, throwing calls in `guard` :4424-4433, `receipt.sourceReceipt` :4658). `swift build` and `swift build --build-tests` are clean on agents@mbp; `git diff --check` clean. 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` (all `receiptMismatch`). 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) throws `sourceUnavailable` for ordinary save/delete when the parent cannot be opened (`testDraftStoreBoundsGrowingFileAndPreservesMalformedFile`, `testDraftStoreRejectsOversizedSnapshotWithoutReplacingExistingDraft`, `testDraftTombstoneRejectsStaleAutosave`, `testEventEditKeepsIdentityAcrossInFlightSuccessFailureAndRestore`, `testQuitKeepsAndRestoresDraft`), `testEmptyEventEditDraftRetainsIdentityAcrossSuspendAndRestore` (CancellationError at ComposerModel.swift:2060), and `testVoiceAttachmentRefusalLeavesCAFWithCallerUntilExplicitDiscard` (caller-owned `discardVoiceRecording(_:)` 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`): - Lane 1 `wave19/first-space-draft-transfer`: restore dev behavior first (gate: ComposerModelTests 22/22), then reviewer items 7 → 9, 8 → 1-4 → 5-6, then `restoreDraft()` of a published transfer and a `spaceTransferFailure`/`retrySpaceTransfer()`/`discardSpaceTransfer()` surface for the UI, then the causal test set. - Lane 2 `wave19/space-handoff-app`: option A app wiring (per-Space `ComposerModel` replacement behind a generation fence; prepare→publish→revalidate→finish on the old model; native Retry/Discard affordance). - Lane 3 `wave19/parent-child-flows`: sidebar Add Note / Add Voice capturing the exact event source into `beginParentTarget`; `AppModel.commit` handling of `.noteWithParent`/`.voiceNoteWithParent` with reread + `expectedSource.matches` CAS and a new `parentSourceChanged` error 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.app` for user acceptance.
Author
Owner

Runtime evidence — chunk A (typed draft follows a Space change) on the VM, 2026-09-14

Build: wave19/first-space-integration @ ea04a2f (= Lane 1 18a2bbb + Lane 3 892de87 + Lane 2 44d4c63 + integration fixes 901dbd6, 9abdee9, 8144203, ea04a2f), Debug app built on agents@mbp, deployed to lume@calternal-macos-vm as ~/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 first restoreDraft(), and (2) first-run adoption; the live vaultSession path is kept.

Steps and observations:

  1. Space "Calternal Overnight Perf QA" open. + → typed "Draft moves with me 123" → Esc. Perf QA/.calternal/drafts/composer.json = {"text":"Draft moves with me 123","mode":"event",…}.
  2. Settings → Choose… → "Calternal Native Break 86ccc9c" → Open Space. Settings shows the new folder and the next-launch notice.
  3. Quit, relaunch. Sidebar footer "Calternal…ak 86ccc9c"; + shows the composer with "Draft moves with me 123".
  4. Filesystem after relaunch: Perf QA drafts dir contains only .composer-recovery.lock; Native Break drafts dir contains composer.json with 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): ComposerVoiceLifecycleTests 15/15, EventAttachmentDropTests 13/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@mbp build: Lane 1 DraftStore corrections (reviewer items 1-6, 8-9) are still in progress on wave19/first-space-draft-transfer (4f6ec94 rollback-owner admission, ef5550c .calternal/drafts/voice traversal 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 A (typed draft follows a Space change) on the VM, 2026-09-14 Build: `wave19/first-space-integration` @ `ea04a2f` (= Lane 1 `18a2bbb` + Lane 3 `892de87` + Lane 2 `44d4c63` + integration fixes `901dbd6`, `9abdee9`, `8144203`, `ea04a2f`), Debug app built on agents@mbp, deployed to `lume@calternal-macos-vm` as `~/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 first `restoreDraft()`, and (2) first-run adoption; the live `vaultSession` path is kept. Steps and observations: 1. Space "Calternal Overnight Perf QA" open. `+` → typed "Draft moves with me 123" → Esc. `Perf QA/.calternal/drafts/composer.json` = `{"text":"Draft moves with me 123","mode":"event",…}`. 2. Settings → Choose… → "Calternal Native Break 86ccc9c" → Open Space. Settings shows the new folder and the next-launch notice. 3. Quit, relaunch. Sidebar footer "Calternal…ak 86ccc9c"; `+` shows the composer with "Draft moves with me 123". 4. Filesystem after relaunch: Perf QA drafts dir contains only `.composer-recovery.lock`; Native Break drafts dir contains `composer.json` with 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): `ComposerVoiceLifecycleTests` 15/15, `EventAttachmentDropTests` 13/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@mbp` build: Lane 1 DraftStore corrections (reviewer items 1-6, 8-9) are still in progress on `wave19/first-space-draft-transfer` (`4f6ec94` rollback-owner admission, `ef5550c` `.calternal/drafts/voice` traversal 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.
Author
Owner

Runtime evidence — chunk B (Add Note under an exact event) on the VM, build ea04a2f:

  • Right-click on sidebar event "Focused work on document navigation" (Sunday 14/06) shows Edit Event / Add Note / Add Voice / Copy Link (Add Note and Add Voice carry SF Symbols; Edit Event and Copy Link currently have none — polish item).
  • Add Note opens the composer in Note mode with an inline row "↪ Adding to Focused work on document navigation" and a native Cancel button.
  • Typed "Parent note via chunk B", ⌘↩. Result in Space "Calternal Native Break 86ccc9c": notes/parent-note-via-chunk-b-09169a8a570d49d795122193334ec60f.md created (frontmatter title + H1), and events/20260614-dailynote.md:11 gained the child link - [Parent note via chunk B](<../notes/parent-note-via-chunk-b-….md>) under that event.
  • Add Voice not exercised on the VM (no audio input); covered by hosted lifecycle tests only.
Runtime evidence — chunk B (Add Note under an exact event) on the VM, build `ea04a2f`: - Right-click on sidebar event "Focused work on document navigation" (Sunday 14/06) shows Edit Event / Add Note / Add Voice / Copy Link (Add Note and Add Voice carry SF Symbols; Edit Event and Copy Link currently have none — polish item). - Add Note opens the composer in Note mode with an inline row "↪ Adding to Focused work on document navigation" and a native Cancel button. - Typed "Parent note via chunk B", ⌘↩. Result in Space "Calternal Native Break 86ccc9c": `notes/parent-note-via-chunk-b-09169a8a570d49d795122193334ec60f.md` created (frontmatter title + H1), and `events/20260614-dailynote.md:11` gained the child link `- [Parent note via chunk B](<../notes/parent-note-via-chunk-b-….md>)` under that event. - Add Voice not exercised on the VM (no audio input); covered by hosted lifecycle tests only.
Author
Owner

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).
  • Merged into wave19/first-space-integration (pushed) with the App rewired to spaceTransferFailure/retrySpaceTransfer()/discardSpaceTransfer() (df73318). Hosted App tests 27/27.
  • VM re-run of chunk A on that build: typed "Second handoff run 456" in Native Break → chose Overnight Perf QA → relaunch: Perf QA .calternal/drafts/composer.json now holds that text, Native Break drafts dir is empty.
  • Third reviewer pass on the Lane 1 diff in progress; a cua-driver patch to post real MouseMoved events (for hover verification on the VM) and XCUITest scenarios on agents@mbp are in progress in parallel. Still no kayg@mbp build for #22 until the review says shippable and a voice-draft run passes on the VM.
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). - Merged into `wave19/first-space-integration` (pushed) with the App rewired to `spaceTransferFailure`/`retrySpaceTransfer()`/`discardSpaceTransfer()` (`df73318`). Hosted App tests 27/27. - VM re-run of chunk A on that build: typed "Second handoff run 456" in Native Break → chose Overnight Perf QA → relaunch: Perf QA `.calternal/drafts/composer.json` now holds that text, Native Break drafts dir is empty. - Third reviewer pass on the Lane 1 diff in progress; a cua-driver patch to post real MouseMoved events (for hover verification on the VM) and XCUITest scenarios on agents@mbp are in progress in parallel. Still no `kayg@mbp` build for #22 until the review says shippable and a voice-draft run passes on the VM.
Author
Owner

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.

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.
Author
Owner

Overnight status (2026-09-14 late):

  • Decision recorded: DECISIONS.md #19 — cooperative DraftStore writers + crash-at-any-boundary are the supported threat model; raw external rewrites of .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.
  • Rounds 4-5 landed on wave19/first-space-draft-transfer: destination reservation (O_CREAT|O_EXCL create, .creating→.reserved→.bound handshake, admission fence on the destination, exact-CAS consume, restart rules), lease-bound voice submissions (.eventWithVoiceLease, .voiceNoteWithParentLease, App consumes via readVoiceBytes() — cf7664a on integration), round-6 recovery fixes (0cc0f18…e140dca: rollbackPending boundary, discard admission, foreign unbound recovery, quarantined payload restoration, voice retry identity, descriptor-bound reservation CAS).
  • Integration 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).
  • Reviewer round 5 verdict was NOT SHIPPABLE; the in-scope items are what round 6 addresses. Round-6 gate (per-method matrix, retained-voice handoff, missing pins) in progress; reviewer round 6 follows, then merge → hosted tests → VM re-run → adversarial pass. Voice cannot be recorded on the VM (no audio input); voice transfer evidence will be test-based plus a seeded-CAF VM run if feasible.
  • No kayg@mbp delivery tonight per user instruction.
Overnight status (2026-09-14 late): - Decision recorded: DECISIONS.md #19 — cooperative DraftStore writers + crash-at-any-boundary are the supported threat model; raw external rewrites of `.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. - Rounds 4-5 landed on `wave19/first-space-draft-transfer`: destination reservation (O_CREAT|O_EXCL create, `.creating`→`.reserved`→`.bound` handshake, admission fence on the destination, exact-CAS consume, restart rules), lease-bound voice submissions (`.eventWithVoiceLease`, `.voiceNoteWithParentLease`, App consumes via `readVoiceBytes()` — `cf7664a` on integration), round-6 recovery fixes (`0cc0f18`…`e140dca`: rollbackPending boundary, discard admission, foreign unbound recovery, quarantined payload restoration, voice retry identity, descriptor-bound reservation CAS). - Integration `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). - Reviewer round 5 verdict was NOT SHIPPABLE; the in-scope items are what round 6 addresses. Round-6 gate (per-method matrix, retained-voice handoff, missing pins) in progress; reviewer round 6 follows, then merge → hosted tests → VM re-run → adversarial pass. Voice cannot be recorded on the VM (no audio input); voice transfer evidence will be test-based plus a seeded-CAF VM run if feasible. - No kayg@mbp delivery tonight per user instruction.
Author
Owner

Round 6 landed (wave19/first-space-draft-transfer @ 6791466, pushed; integration wave19/first-space-integration @ 29d22d4, pushed):

  • Fixes: rollbackPending crash boundary (0cc0f18), reservation .creating handshake (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).
  • Build host: ComposerSpaceTransferTests 38/38 per-method, ComposerParentTargetTests 15/15, ComposerModelTests 26/26, VoiceFrozenClaimTests 9/9, VoiceDraftRecoveryTests 40 with the 3 accepted dev-baseline fixture failures; hosted App tests 28/28.
  • VM (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.
  • Reviewer round 6 (under DECISIONS.md #19): text-only blocked by ONE item — the .creating reservation 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.
Round 6 landed (`wave19/first-space-draft-transfer` @ `6791466`, pushed; integration `wave19/first-space-integration` @ `29d22d4`, pushed): - Fixes: rollbackPending crash boundary (`0cc0f18`), reservation `.creating` handshake (`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`). - Build host: ComposerSpaceTransferTests 38/38 per-method, ComposerParentTargetTests 15/15, ComposerModelTests 26/26, VoiceFrozenClaimTests 9/9, VoiceDraftRecoveryTests 40 with the 3 accepted dev-baseline fixture failures; hosted App tests 28/28. - VM (`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. - Reviewer round 6 (under DECISIONS.md #19): text-only blocked by ONE item — the `.creating` reservation 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.
Author
Owner

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:

  • Lane ComposerSpaceTransferTests: Executed 42 tests, with 0 failures (0 unexpected).
  • Lane ComposerParentTargetTests: Executed 15 tests, with 0 failures (0 unexpected).
  • Lane ComposerModelTests: Executed 26 tests, with 0 failures (0 unexpected).
  • Lane VoiceFrozenClaimTests: Executed 9 tests, with 0 failures (0 unexpected).
  • Lane VoiceDraftRecoveryTests: Executed 40 tests, with 3 accepted dev-baseline failures only at VoiceDraftRecoveryTests.swift:886/:892/:902.
  • Lane package: Scripts/build-mbp.sh first-space-draft-transfer package completed.
  • Integration app: BUILT_APP=/Users/agents/Developer/Worktrees/first-space-integration/App/build/Build/Products/Debug/Calternal.app.
  • Hosted integration command: ComposerVoiceLifecycleTests Executed 15 tests, with 0 failures; EventAttachmentDropTests Executed 14 tests, with 0 failures; combined Executed 29 tests, with 0 failures; ** TEST SUCCEEDED **.
    The integration worktree is clean and no push was performed.
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 f602d2978ef2df43f5008d0a7a64a50baf690343. 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 @ 9e253af30974aae064e70a68cbc826532d57e794; no Lane 1 edits were made, so no merge was required. Validation evidence on agents@mbp: - Lane ComposerSpaceTransferTests: Executed 42 tests, with 0 failures (0 unexpected). - Lane ComposerParentTargetTests: Executed 15 tests, with 0 failures (0 unexpected). - Lane ComposerModelTests: Executed 26 tests, with 0 failures (0 unexpected). - Lane VoiceFrozenClaimTests: Executed 9 tests, with 0 failures (0 unexpected). - Lane VoiceDraftRecoveryTests: Executed 40 tests, with 3 accepted dev-baseline failures only at VoiceDraftRecoveryTests.swift:886/:892/:902. - Lane package: Scripts/build-mbp.sh first-space-draft-transfer package completed. - Integration app: BUILT_APP=/Users/agents/Developer/Worktrees/first-space-integration/App/build/Build/Products/Debug/Calternal.app. - Hosted integration command: ComposerVoiceLifecycleTests Executed 15 tests, with 0 failures; EventAttachmentDropTests Executed 14 tests, with 0 failures; combined Executed 29 tests, with 0 failures; ** TEST SUCCEEDED **. The integration worktree is clean and no push was performed.
Author
Owner

Round 7 landed (Lane 1 @ 9e253af, integration @ f602d29, both pushed): flock-based liveness handshake for .creating reservations (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 .creating reservation (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 7 landed (Lane 1 @ `9e253af`, integration @ `f602d29`, both pushed): flock-based liveness handshake for `.creating` reservations (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 `.creating` reservation (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.
Author
Owner

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; 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.
Author
Owner

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 .creating reservation 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.

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 `.creating` reservation 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.
Author
Owner

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: 20f0036 missing reservation lock lease; 2815cd2 close stale lock without successor pathname unlink; 0ca1c5c retained manifest adoption gate; 06dd22c exact rollback baseline gate; 6deaab7 live retained CAF requirement; 522122f live CAF receipt rebinding; 62000f6 retained transcript persistence; 39bf26f receipt binding correction; f0e6e9f missing-lock pin; 5587159 retained 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.

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: 20f0036 missing reservation lock lease; 2815cd2 close stale lock without successor pathname unlink; 0ca1c5c retained manifest adoption gate; 06dd22c exact rollback baseline gate; 6deaab7 live retained CAF requirement; 522122f live CAF receipt rebinding; 62000f6 retained transcript persistence; 39bf26f receipt binding correction; f0e6e9f missing-lock pin; 5587159 retained 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.
Author
Owner

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 include 4e72310 on top of the prior round-9 commits.

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 include 4e72310 on top of the prior round-9 commits.
Author
Owner

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 after 4e72310. Worktree clean.

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 after 4e72310. Worktree clean.
Author
Owner

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.json present 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 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.json` present 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.
Author
Owner

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) with TransferControlRecordTests 3/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): ceff4bf phase-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 (cacheIneligible while seeding) before the final gate; then VM text + seeded-voice runs, then a build is staged for the user.

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) with `TransferControlRecordTests` 3/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`): `ceff4bf` phase-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 (`cacheIneligible` while seeding) before the final gate; then VM text + seeded-voice runs, then a build is staged for the user.
Author
Owner

FINAL STATE for user acceptance (2026-09-15):

  • Library 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).
  • App integration 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.
  • VM (real events, Scripts/vm/space_handoff_check.py): typed draft in Overnight Perf QA → Settings → Go to Folder → Native Break → quit/relaunch → composer.json present 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.
  • Voice: library-level transfer of stopped and retained recordings is pinned (hosted testPreviousVaultBookmarkTransfersRetainedVoiceBeforeFirstRestore etc.); 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 (revision 328de5d); it will be copied to kayg@mbp:~/Applications/Calternal.app only on the user's go-ahead. Remaining before merge to dev: user acceptance; performance profile of the launch handoff; merge of wave19/block-editor-craft is separate (#3/#4/#24).

FINAL STATE for user acceptance (2026-09-15): - Library `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). - App integration `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. - VM (real events, `Scripts/vm/space_handoff_check.py`): typed draft in Overnight Perf QA → Settings → Go to Folder → Native Break → quit/relaunch → `composer.json` present 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. - Voice: library-level transfer of stopped and retained recordings is pinned (hosted `testPreviousVaultBookmarkTransfersRetainedVoiceBeforeFirstRestore` etc.); 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` (revision 328de5d); it will be copied to `kayg@mbp:~/Applications/Calternal.app` only on the user's go-ahead. Remaining before merge to dev: user acceptance; performance profile of the launch handoff; merge of `wave19/block-editor-craft` is separate (#3/#4/#24).
Author
Owner

FINAL STATE for user acceptance (2026-09-15):

  • Library 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).
  • App integration 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.
  • VM (real events, Scripts/vm/space_handoff_check.py): typed draft in Overnight Perf QA → Settings → Go to Folder → Native Break → quit/relaunch → composer.json present 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.
  • Voice: library-level transfer of stopped and retained recordings is pinned (hosted testPreviousVaultBookmarkTransfersRetainedVoiceBeforeFirstRestore etc.); 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 (revision 328de5d); it will be copied to kayg@mbp:~/Applications/Calternal.app only on the user's go-ahead. Remaining before merge to dev: user acceptance; performance profile of the launch handoff; merge of wave19/block-editor-craft is separate (#3/#4/#24).

FINAL STATE for user acceptance (2026-09-15): - Library `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). - App integration `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. - VM (real events, `Scripts/vm/space_handoff_check.py`): typed draft in Overnight Perf QA → Settings → Go to Folder → Native Break → quit/relaunch → `composer.json` present 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. - Voice: library-level transfer of stopped and retained recordings is pinned (hosted `testPreviousVaultBookmarkTransfersRetainedVoiceBeforeFirstRestore` etc.); 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` (revision 328de5d); it will be copied to `kayg@mbp:~/Applications/Calternal.app` only on the user's go-ahead. Remaining before merge to dev: user acceptance; performance profile of the launch handoff; merge of `wave19/block-editor-craft` is separate (#3/#4/#24).
Author
Owner

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 integration 328de5d).

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 in 18a2bbb); per-Space ComposerModel/DraftStore rebinding 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 328de5d at kayg@mbp:~/Applications/Calternal.app still contains the transfer; do not evaluate the transfer behavior. A replacement build follows after the cut is reviewed and verified.

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 integration 328de5d). 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 in 18a2bbb); per-Space `ComposerModel`/`DraftStore` rebinding 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 `328de5d` at `kayg@mbp:~/Applications/Calternal.app` still contains the transfer; do not evaluate the transfer behavior. A replacement build follows after the cut is reviewed and verified.
Author
Owner

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; VM Scripts/vm/per_space_draft_check.py 4/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.

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; VM `Scripts/vm/per_space_draft_check.py` 4/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.
Author
Owner

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/testFailedRestartRetainsLastRecordingAndAllowsAnotherAttempt hangs at its very first await firstSession.lifecycle.waitUntilStarted() (log stops right after the test starts) — i.e. the first toggleRecording is 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 show is not permitted for the agents user). Deferred: not part of the morning build (this branch installs separately); resume after the visual lanes land.

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/testFailedRestartRetainsLastRecordingAndAllowsAnotherAttempt` hangs at its very first `await firstSession.lifecycle.waitUntilStarted()` (log stops right after the test starts) — i.e. the first `toggleRecording` is 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 show` is not permitted for the agents user). Deferred: not part of the morning build (this branch installs separately); resume after the visual lanes land.
Sign in to join this conversation.
No labels
No milestone
No project
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
No description provided.