[on hold] feat(tasks): add guarded status actions #801
Closed
kayg
wants to merge 1 commit from
feat/tasks-set-status into dev
pull from: feat/tasks-set-status
merge into: kayg:dev
kayg:main
kayg:feat/style-sheet-fixes
kayg:storage/wal-checkpoint-off-save-1051
kayg:t3/paged-search-reconcile-final
kayg:feat/pass8
kayg:review/calendar-2
kayg:fix/shared-row-swipes
kayg:feat/contrast
kayg:dev
kayg:feat/collections-db
kayg:fix/instant-keys-1056
kayg:feat/money-round
kayg:perf/stalls-1054
kayg:wip/tiering-v3-cold4
kayg:wip/tiering-v3-cold5
kayg:port/rows-actions
kayg:port/rows-drop
kayg:port/hidden-blocks
kayg:port/rows
kayg:port/port-tables
kayg:port/port-tables-2
kayg:t3/mail-1011-liveness
kayg:port/devices
kayg:port/port-attachments
kayg:port/port-attachments-2
kayg:port/port-attachments-3
kayg:docs/design-consistency
kayg:docs/engineering-standards
kayg:fix/rusqlite-0.41-rustsec-2026-0459
kayg:feat/iphone-fixes
kayg:shared/restore-and-stale-918-919
kayg:fix/phone-top-band-contrast
kayg:feat/notes-approve
kayg:perf/soak-max-gate
kayg:feat/files-s1-identity
kayg:fix/lifecycle-event-id
kayg:feat/quickfix
kayg:wip/tiering-v3-cold
kayg:perf/web-mockup-frame-fixes
kayg:port/contacts-merge
kayg:port/contacts-edit
kayg:test/shared-room-no-deleted-text
kayg:perf/first-paint-credits
kayg:fix/shared-history-after-grant
kayg:fix/phone-swipe-regressions
kayg:feat/contrast-r1
kayg:review/sharing-pr3-review
kayg:feat/tiering-v3-s2-tags
kayg:feat/folder-drop
kayg:fix/deskpills-lazy-share
kayg:feat/sharing-s1-pr3
kayg:tmp/money-round-before
kayg:fix/phone-pane-backdrop-roots
kayg:fix/palette-preload-chips
kayg:fix/invite-defaults
kayg:port/tasks-matrix
kayg:fix/restore-green-gates
kayg:fix/sharing-fast-path-hardening
kayg:t3/photos-s1
kayg:feat/tiering-v3-s1-namespace
kayg:notes-archive-hide
kayg:feat/tasks-actions
kayg:t3/photos-plan-slice-one
kayg:feat/whiteboard-s1
kayg:t3/paged-search-reconcile
kayg:t3/smooth-pane-transitions
kayg:t3/index-position-startup-scan
kayg:fix/private-staging-759b-r2
kayg:feat/dav-transport
kayg:feat/imap-notes-fetch
kayg:feat/imap-notes-projection
kayg:feat/imap-notes-readonly
kayg:feat/imap-notes-auth
kayg:feat/imap-notes-server-foundation
kayg:docs/undo-block-ids-plan
kayg:fix/undo-768
kayg:proto/block-identity-v7d
kayg:issue/carddav-read-perf-fix-r2
kayg:issue/carddav-read-r2
kayg:docs/imap-766-plan-v2
kayg:docs/imap-notes-plan
kayg:docs/quota-plan-2
kayg:fix/parallel-test-flakes
kayg:feat/contacts-companion-pure
kayg:docs/calendar-backend-v2-plan
kayg:feat/calendar-ical-converter
kayg:docs/tasks-writes-v2-plan
kayg:docs/carddav-writes-v2-plan
kayg:docs/contacts-import-v2-plan
kayg:issue/610-pm-midnight
kayg:feat/calendar-v2-s1-containment
kayg:docs/dav-recorder-v2-plan
kayg:plan/previews-865
kayg:plan/save-log-durable-entry
kayg:fix/e2e-data-on-ram
kayg:feat/appwindow3
kayg:feat/appwindow2
kayg:feat/appwindow
kayg:feat/money-p1
kayg:feat/keys-sheet
kayg:review/calendar-2-themes
kayg:feat/smooth-cursor
kayg:fix/float-style
kayg:review/calendar-2-float
kayg:release/2026-11-06-hotfix
kayg:archive/port/rows-drop-code
kayg:archive/port/rows-actions
kayg:archive/port/rows
kayg:scratch/tasks-894-ui-gates
kayg:review/calendar-2-night-wip
kayg:release/2026-11-05
kayg:archive/feat/tiering-v3-s1-namespace
kayg:archive/flaky/rows-drop-fixed
kayg:archive/flaky/rows-actions
kayg:archive/feat/tiering-v3-reader
kayg:archive/feat/tiering-v3-roots
kayg:archive/flaky/rows
kayg:sim/bm15-final
kayg:sim/bm15-fix
kayg:sim/bm15-bis-932
kayg:sim/bm15-bis-909
kayg:sim/bm15
kayg:sim/bm15-bis-887
kayg:perf/tiering-option-b
kayg:port/style-3
kayg:port/style-2
kayg:port/style
kayg:fix/sw-lazy-precache
kayg:fix/vim-w-waits-for-save
kayg:fix/signout-test-races
kayg:fp-scratch/all
kayg:sim/bm15-first-paint
kayg:archive/bm15/rows-drop
kayg:archive/bm15/rows-actions
kayg:fix/palette-snippet-contrast
kayg:archive/bm15/rows
kayg:archive/bm15/hidden
kayg:archive/plan/save-log-durable-entry
kayg:mock/money-fix2
kayg:archive/fix/e2e-data-on-ram
kayg:mock/appearance-all
kayg:mock/pill-press
kayg:archive/docs/design-consistency
kayg:mock/auto-swipes
kayg:mock/mail-actions
kayg:archive/feat/mail-p1
kayg:mock/money-static
kayg:archive/review/standards-917
kayg:archive/docs/engineering-standards
kayg:perf/tiering-761-fix
kayg:mock/type-audit
kayg:mock/third-pane
kayg:feat/contacts-import-v2-s1
kayg:perf/executor-hot-path
kayg:archive/port/hidden-blocks
kayg:archive/port/devices
kayg:scratch/executor-on-894
kayg:scratch/executor-spans2
kayg:scratch/executor-spans
kayg:train/2026-11-03-bm14c
kayg:archive/port/rows-drop
kayg:feat/tiering-761-d-scale
kayg:feat/tiering-761-c-index
kayg:feat/tiering-761-b-reader
kayg:archive/review/sharing-pr3-review-9fec3d1f
kayg:train/2026-11-03-bm14b
kayg:perf/ports-lazy-budgets
kayg:feat/tiering-761-a-migration
kayg:train/2026-11-03-bm14
kayg:train/2026-11-03-bm12
kayg:archive/review/sharing-pr3-review
kayg:archive/feat/sharing-s1-pr3
kayg:train/2026-11-03-bm11
kayg:archive/feat/imap-notes-fetch
kayg:train/2026-11-03-bm10
kayg:archive/review/sharing-pr3-review-code
kayg:archive/plan/previews-865
kayg:train/2026-11-02-bm9
kayg:archive/port/port-attachments-3
kayg:archive/port/contacts-merge
kayg:fix/motion-audit-859
kayg:train/2026-11-02-bm8
kayg:archive/scratch/bm8-prep
kayg:archive/port/port-pickers
kayg:archive/port/port-tables-2
kayg:archive/port/port-tables
kayg:archive/feat/sharing-s1-pr3-code
kayg:archive/scratch/bm7-fixed
kayg:train/2026-11-02-bm7
kayg:archive/fix/parallel-test-flakes-code-minipc01
kayg:train/2026-11-02-bm6
kayg:docs/imap-766-readonly-slice
kayg:feat/dav-recorder-v3
kayg:research/788-diagnosis
kayg:archive/fix/parallel-test-flakes
kayg:archive/perf/pr792-cold-index-edit
kayg:docs/sharing-slice-1
kayg:archive/docs/imap-766-plan-v2
kayg:feat/dav-recorder-v2
kayg:archive/docs/dav-recorder-v2-plan
kayg:spike/imap-766-s0-cases
kayg:archive/fix/undo-768
kayg:feat/dav-recorder
kayg:archive/docs/contacts-import-v2-plan
kayg:archive/feat/calendar-ical-converter
kayg:feat/contacts-import
kayg:perf/cold-growth-on-764
kayg:perf/cold-growth-on-tiering
kayg:archive/docs/tasks-writes-v2-plan
kayg:archive/docs/calendar-backend-v2-plan
kayg:archive/feat/contacts-companion-pure
kayg:feat/tasks-move-reorder
kayg:archive/docs/carddav-writes-v2-plan
kayg:archive/feat/calendar-v2-s1-containment
kayg:feat/tasks-delete-promote-duplicate
kayg:archive/feat/dav-transport
kayg:archive/fix/carddav-rebuild-r1
kayg:archive/fix/carddav-retention-r1
kayg:feat/carddav-writes
kayg:perf/quota-on-tiering
kayg:perf/quota-simple
kayg:perf/cold-growth-on-quota-stack
kayg:feat/calendar-identity
kayg:feat/calendar-event-parser
kayg:feat/calendar-props-maps
kayg:port/glass-when-ring
kayg:feat/tiering-761-s1
kayg:wip/10by32-01-impl-759b-scratch-20261030
kayg:wip/6by32-01-bm3-webkit-pause-20261030
kayg:wip/10by32-01-bm3-chromium-pause-20261030
kayg:wip/6by32-01-tier-761-s1-pause-20261030
kayg:spike/imap-766-s0
kayg:wip/6by32-02-calternal-pause-20261030
kayg:wip/8by64-01-review-688-pause-20261030
kayg:wip/6by32-01-verify-744-pause-20261030
kayg:wip/6by32-01-verify-742-pause-20261030
kayg:fix/private-staging-759b
kayg:wip/6by32-01-review-748-pause-20261030
kayg:wip/6by32-01-review-733c-pause-20261030
kayg:wip/6by32-01-review-733b-pause-20261030
kayg:wip/6by32-01-perf-idle-8-pause-20261030
kayg:wip/6by32-01-perf767-base-pause-20261030
kayg:wip/6by32-01-perf767b-767-pause-20261030
kayg:wip/6by32-01-perf767b-764-pause-20261030
kayg:wip/6by32-01-perf767-767-pause-20261030
kayg:wip/6by32-01-perf767-764-pause-20261030
kayg:wip/6by32-01-lists-b-pause-20261030
kayg:wip/6by32-01-ids-verify5-pause-20261030
kayg:wip/6by32-01-ids-verify4-pause-20261030
kayg:review/calendar-month
kayg:wip/10by32-02-undo-768-20261030
kayg:test/ids-verify3
kayg:wip/10by32-02-bm3-chromium-20261030
kayg:wip/10by32-01-review-753-20261030
kayg:wip/10by32-01-perf-idle-2-20261030
kayg:wip/10by32-01-bm2-webkit2-20261030
kayg:plan/759b-staging
kayg:train/2026-10-30-bm2
kayg:review/758b-tests
kayg:review/758-tests
kayg:review/764d-tests
kayg:review/767b-tests
kayg:review/preview-2026-10-29
kayg:review/767-tests
kayg:docs/tiering-731-plan
kayg:wip/c6b02-when2
kayg:wip/c6b02-tasks-create-fix5
kayg:wip/c6b02-settings-frost-mock
kayg:wip/c6b02-settings-frost-base
kayg:wip/c6b02-settings-frost
kayg:wip/c6b02-ring
kayg:wip/c6b02-review-733d
kayg:wip/c6b02-bm1-full-a
kayg:wip/compute02-when-field
kayg:wip/compute02-webkit-lists-repro
kayg:wip/compute02-train-bl2-dev
kayg:wip/compute02-dev-green-pw164
kayg:docs/deploy-plan
kayg:review/764c-tests
kayg:review/764b-tests
kayg:review/748g-tests
kayg:review/764-tests
kayg:review/759b-tests
kayg:fix/storage-owner-liveness-642
kayg:fix/storage-fix-7
kayg:wip/compute02-storage-fix-7
kayg:review/759-tests
kayg:feat/tiering-731
kayg:wip/tiering-731-first-attempt
kayg:wip/compute02-storage-fix-1
kayg:review/754g-tests
kayg:perf/idle-honest-2
kayg:review/754f-tests
kayg:review/754e-tests
kayg:review/755-tests
kayg:review/754d-tests
kayg:review/754c-tests
kayg:review/754b-tests
kayg:review/754-tests
kayg:fix/storage-private-tmp-642-dev
kayg:wip/compute02-verify-750
kayg:test/ids-verify5
kayg:test/ids-verify4
kayg:fix/storage-exact-file-quarantine-642
kayg:wip/compute02-verify-740
kayg:perf/one-flush-save
kayg:review/calendar-static
kayg:wip/compute02-verify-737
kayg:review/indexing-ring
kayg:review/when-field-2
kayg:wip/compute02-review-733
kayg:proto/block-identity-2-review
kayg:proto/block-identity-review
kayg:wip/c6b02-tc-design
kayg:review/when-field
kayg:issue/tasks-create-ids
kayg:issue/tasks-create
kayg:review/combined
kayg:wip/compute02-review-combined
kayg:review/task-polish
kayg:review/top-buttons
kayg:review/q1-q5
kayg:train/2026-10-26-bl2
kayg:archive/wt-398h
kayg:archive/train-bm-proptest-seed
kayg:archive/integ325-293
kayg:archive/integ325-ci
kayg:archive/client-auth-review-baseline
kayg:archive/wt-sim-4853
kayg:archive/wt-sim-4811
kayg:archive/wt-448m
kayg:archive/wt-398a-allocator
kayg:issue/calendar-adr
kayg:archive/old/train/2026-10-23bk2
kayg:archive/old/train/2026-10-23bk
kayg:issue/469-mockup-9a
kayg:issue/smart-tasks-mockup
kayg:issue/469-menus
kayg:issue/652-signout-flake
kayg:issue/652-history-fix7
kayg:issue/652-history-fix6
kayg:archive/old/issue/spring-check-perf
kayg:issue/spring-check-perf
kayg:issue/659-rename-fast
kayg:archive/old/train/2026-10-21ar
kayg:issue/search-hardening-3
kayg:issue/652-history-fix5
kayg:issue/660-port-sheets-glass
kayg:issue/652-history-fix4
kayg:issue/652-history-fix3
kayg:issue/652-history-fix2
kayg:issue/652-history-flake
kayg:train/2026-10-21an
kayg:issue/settings-admin-port
kayg:issue/search-port
kayg:train/2026-10-20am
kayg:issue/storage-split-fix2
kayg:issue/storage-split
kayg:archive/old/issue/folder-ids-fix
kayg:train/2026-10-20al
kayg:archive/old/issue/folder-ids
kayg:train/2026-10-20ak
kayg:issue/tables-mockup
kayg:train/2026-10-19aj
kayg:train/2026-10-19ai
kayg:issue/469-merge-fixes
kayg:issue/sidebar-band
kayg:archive/old/issue/608-settings-spec
kayg:train/2026-10-19ah
kayg:issue/swipe-offscreen
kayg:train/2026-10-19ag
kayg:archive/old/issue/590-nlp-adr
kayg:archive/old/issue/587-event-after-write-2
kayg:train/2026-10-19af
kayg:archive/old/issue/587-event-after-write
kayg:issue/469-pill-room-c
kayg:issue/469-pill-room
kayg:train/2026-10-19ae
kayg:issue/469-narrow-handle
kayg:issue/397-ios-swipe-2
kayg:archive/old/issue/adrs-photos-files-tasks
kayg:issue/469-desk-fixes
kayg:archive/old/issue/auto-update-adr
kayg:issue/469-filter-gap
kayg:issue/469-port-1b
kayg:issue/442-opacity-flake
kayg:archive/397-ios-swipe-2
kayg:issue/327-web-fast-3
kayg:archive/old/issue/469-port-1
kayg:issue/469-port-1
kayg:issue/327-web-fast-2
kayg:archive/old/issue/327-web-fast
kayg:archive/old/issue/425-stt-bench-vq1
kayg:archive/old/issue/445-no-bleed
kayg:archive/old/issue/400-swipe-mockup-2
kayg:issue/426-client-review
kayg:issue/426-client-2
kayg:issue/426-client
kayg:archive/old/issue/476-safe-area-lab
kayg:archive/445-top-light-2
kayg:archive/old/issue/445-top-light
kayg:issue/471-blocks-mockup
kayg:archive/old/issue/448-links-app-2
kayg:archive/old/issue/448-links-app
kayg:archive/old/issue/398-cold-links
kayg:issue/434-442-small-2
kayg:issue/434-442-small
kayg:archive/old/issue/398-unload
kayg:archive/old/issue/445-bottom-band
kayg:issue/445-bottom-band
kayg:issue/351-rem-3
kayg:archive/312-views-mockup
kayg:issue/351-rem-2
kayg:issue/351-rem
kayg:archive/old/issue/327-first-note
kayg:issue/395-width-phone
kayg:archive/old/issue/327-typing
kayg:issue/396-ios-edges
kayg:issue/397-ios-swipe
kayg:archive/398-allocator
kayg:archive/old/issue/327-notes-index
kayg:issue/345-347-contrast-empty-2
kayg:archive/old/issue/44-arenas
kayg:issue/44-arenas
kayg:archive/integ325
kayg:archive/old/issue/327-perf-harness
kayg:archive/old/issue/44-thp
kayg:issue/44-thp
kayg:archive/old/issue/285-sticky-pills
kayg:archive/old/issue/44-trim-3
kayg:issue/44-trim-3
kayg:archive/old/issue/165-cards
kayg:archive/old/issue/165-picker-2
kayg:archive/old/issue/212-multi-select
No reviewers
Labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
kayg/calternal!801
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/tasks-set-status"
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?
ON HOLD by owner decision. Pending
docs/plans/0066-tasks-writes-v2.md: a pure planner of exact splices plus ONE journaled executor for apply, recovery and undo across all task actions. Current implementation and regression tests are preserved; do not merge.Plan
This plan is the first change in the PR. The implementation follows the
accepted task model and the additional B1 constraints from the task brief.
Scope and size
Size: M. One and many status actions, a guarded notes job API, generated
action types, and focused tests; target under 800 production lines, excluding
tests and the plan.
tasks.set-statuschanges one task.tasks.set-status-manyapplies one status selection as one undoable job.todo,doing,done,cancelled, andsomeday.statuskey and every owningcheckbox.
donestampscompleted;cancelledstampscancelled; otherstatuses clear both outcome timestamps. A checkbox edit replaces only its
parsed mark character.
master stays open and its checkbox lines remain open; its
loglist recordsthe completed occurrence by that link. Repeating the same link is a no-op.
The event/session writer remains the source of the link; this action does
not invent a session line.
tasks.getreturns that versionfor the next status edit.
exact
notes.undo; the idempotency key identifies both the request and job.Safety and file format
Frontmatter changes go through
crates/notes/src/props.rs. Before the writerruns, status edits refuse malformed or non-simple frontmatter, including
comments, flow collections, anchors/aliases, multiline scalars, and quotes
embedded in plain scalars, CRLF, and BOM. No fallback YAML writer is added. Accepted status
and
logedits must preserve every byte outside their target property lines.Checkbox candidates come from the existing CommonMark parser in
crates/tasks/src/found.rs. No checkbox-looking text inside fenced code,inline or multiline code spans, or HTML comments is actionable. The resulting
edit changes only the mark returned by that parser. The guarded step checks
the room version and re-reads the raw file before applying the patch. It
refuses a mismatch, preserves existing note metadata, and records its
receipt before file placement. Undo uses the existing guarded splice.
A failed job remains a refusal when its request key is retried.
Complexity
Let
Kbe selected tasks,Ltheir indexed owning checkbox lines,Nthedistinct notes containing those lines, and
Bthe total bytes in those notes.Single status lookup is
O(log T + L + B); many isO(K log T + L + B).The durable plan is
O(B + K + L): it stores the expected text of eachnote once for exact byte checks, plus the forward and inverse edits. There is no Home-wide scan.
Failure table
propsvalidation and safe-format guardnotes.undowith returned jobTests and gates
change only the target property lines; reject each unusual YAML form above.
and single/multiline HTML comments.
stale versions, one-job many updates, recurring log-link dedupe/untick,
idempotent replay, crash replay, and exact undo.
cargo fmt --all --check;cargo clippy --workspace --all-targets -- -D warnings; tests forcalternal-tasks,calternal-notes, andcalternal; the action contract test and generated web action types; webtypecheck.
Decisions and costs if wrong
requested in the integrated task/event model. It is stored as a list item in
log; this differs from the older outcome-map example in ADR 0068. If thatexample remains normative, the log representation will need an ADR update.
task notes. This is intentional for B1: unsafe formatting is never guessed
through or normalized.
Resume findings
Tasks/while creating notes at the Homeroot. They now link to the actual fixture paths.
corpus now asserts the parser emits a code event containing its fake box.
reaches the durable batch boundary before reopening the Home.
are now parsed from the planned text after its property edits.
Validation
Run on dev-01 inside
nix develop -c bash -c, with heavy commands through~/bin/slot(the final gate sequence held one slot throughout):cargo fmt --all --check: passed.cargo clippy --workspace --all-targets -j4 -- -D warnings: passed.cargo test -j4 -p calternal-tasks -p calternal-notes: the notes suitepassed 445 tests, with 6 ignored. The task fixture failures in this first
invocation were corrected and verified by the final run below.
cargo test -j4 -p calternal-tasks -p calternal: 55 task tests and 61server tests passed; 4 server tests ignored.
UPDATE_CONTRACTS=1 cargo test -j4 -p calternal contract, thencargo test -j4 -p calternal contract: passed.node apps/web/scripts/action-types.mjs --check: passed.bun install --frozen-lockfile, thencd apps/web && bun run check:passed, 0 errors and 14 warnings in unchanged Svelte files.
The recurring crash test cancels/reopens at the durable batch boundary. The
notes suite separately exercises real kill-9 recovery; this PR does not add
a task-specific process-kill matrix. The journal's existing partial-failure
semantics remain: a late source conflict refuses its step, and completed
steps can be undone. Recurrence advancement and watcher reconciliation remain
separate work; B1 records caller-supplied session links.
Head:
b91d8ab0ac701bb8f4e63d71e46ce0e2ea86b833. Ready for review; do not merge.tasks: add status actionsto feat(tasks): add guarded status actionsIndependent review, round 1
Verdict: fix first. Reviewed
b91d8ab0ac701bb8f4e63d71e46ce0e2ea86b833. P0: none identified.P1: the exact-byte guard ends before file placement
crates/notes/src/room/edit.rs:137–173checks the raw file before recording the edit, butbulk/steps.rs:69–95subsequently flushes through the ordinary save path. On a placement conflict,room/save.rs:232–237ingests the outside bytes and retries without repeatingvalidate_patchableor comparing against the status step's expected bytes. Recovery similarly replays history and merges outside bytes inroom/load.rs, and an existing edit receipt returns before the ExactPatch guard.Concrete boundary: pause a CheckedEdit before file placement, externally change
status: todotostatus: cancelledand/or change the file to CRLF, then resume. The flush can merge and publish against bytes the action never validated instead of refusing. If that note also contains an owning checkbox, whole-key frontmatter resolution can retain the outside status while the pending checkbox becomes[x]. This is beyond the documented refusal with undoable earlier steps.Carry the checked step's expected raw bytes/hash through actual atomic placement and recovery. For checked writes, refuse a mismatch rather than ingesting and retrying it as an ordinary edit. Keep the receipt/recovery state sufficient to distinguish an already placed result from an unapplied/conflicted one.
P1: undo discards the checked-write contract and can duplicate frontmatter keys
crates/notes/src/bulk/undo.rs:104–122turns CheckedEdit into an ordinary Splice. Its path throughroom/delete.rs:97–125ingests/saves before the splice guard and never callsvalidate_patchable. The guard inbulk/guard.rschecks only characters an inverse deletes; it does not protect properties an inverse reinserts.Example: start with
status: doneandcompleted: <old timestamp>, set todo (removing completed), then let an outside editor addcompleted: <new timestamp>while retaining todo. Undo's inverse can restore the old completed line beside the new one: the status text being replaced is still unchanged, so its span guard passes. The result has duplicate completed keys. CRLF/BOM/unsupported YAML introduced after the action also bypasses the new refusal contract on this path.Use a checked inverse for status jobs, validating raw bytes and YAML before any write, and protect the absence of any property being restored. The simplest conservative implementation refuses undo after the expected post-action note changes; any more permissive inverse needs whole-key preconditions as well as character-span checks.
P2: status sync overwrites unsupported checkbox symbols
crates/tasks/src/status.rs:297–313rewrites every linked parsed mark, including[?]and other custom symbols, becausefounddeliberately retains them. ADR 0066 says unknown custom symbols must be retained and are unsupported in v1. Refuse the affected action during preflight rather than silently replacing a custom symbol with a standard status mark.Atomicity and parser assessment
The proposed simplest same-note fix is already present:
status.rs:344–356emits one CheckedEdit per distinct note after combining its properties and checkbox changes, and save places one complete note image atomically. Recurring ticks change only singularlog, leaving the master boxes alone. I found no separate same-note checkbox/log write boundary that a crash alone could split. Cross-note partial jobs remain the documented limitation. Keep this grouping while fixing the guard paths above.The new YAML guard explicitly covers the requested plain-value interior quotes, list comments, flow collections, multiline values, CRLF and BOM. CommonMark item events exclude checkbox-looking content in code spans, fences and comments; the multiline span fixture explicitly verifies that it is a real code span. No additional blocker identified in those parsing paths by inspection.
Validation limits
This is a code-inspection review, not a claim of passing new runtime tests. Three uncommitted probes are in dev-01's
~/Developer/Worktrees/review-801-r1/crates/notes/src/room/save/tests.rs:review801_exact_patch_late_outside_write,review801_undo_encoding_guard, andreview801_undo_duplicate_property. All five dev-01 slots and both dev-02 slots were occupied; I cancelled only my queued unit before Cargo started. To run on dev-01 in that worktree:nix develop -c bash -c 'CARGO_TARGET_DIR=/home/claude/Developer/Worktrees/tasks-set-status/target ~/bin/slot cargo test -j4 -p calternal-notes review801 -- --nocapture'. The Nix overlay and probes remain uncommitted. No code pushed.round 1 implementation plan (size m): retain one complete note image per CheckedEdit. add one shared raw-byte/format guard for initial apply, receipt replay, atomic placement, recovery and checked undo. persist before/after images beside the keyed receipt; only receipts with committed edits activate recovery. undo swaps the captured images and refuses any changed post-image. preserve one write per distinct note; refuse custom checkbox marks during preflight.
cost: O(B) time and retained bytes per changed note, O(log R) receipt lookup.
will run fmt, workspace clippy -D warnings, tasks/notes/calternal tests, contract and action-types check on dev-01 through slot. no merge.
coordination update: merged
origin/feat/tasks-delete-promote-duplicateatf1600ed0. B1 now reusescrates/notes/src/task_ops.rs::verify_target(note, expected_source_bytes, expected_kind). its checked-image adapter adds UTF-8/simple-format validation and carries the images through flush, crash recovery, receipt replay and undo; no competing byte/kind implementation.same-note checkbox/log edits remain one complete atomic image. added a 16-case runtime-loss matrix (prepare, before placement, placement, after placement × forward/undo × unchanged/outside CRLF), receipt replay and custom-mark regressions. the three original reviewer probes reproduced failures on
b91d8ab0. gate run is queued on dev-01 behind occupied slots. no merge into dev.feat(tasks): add guarded status actionsto [on hold] feat(tasks): add guarded status actionson hold pending the shared Tasks writes v2 plan, per owner direction. stopped further fixes and gate runs. expected plan:
docs/plans/0066-tasks-writes-v2.md, pure exact-splice planner + ONE journaled executor covering apply, recovery and undo for every action.preserved and pushed head
ac9bceb1. the three reviewer probe tests are committed as regressions, together with crash-boundary, receipt and custom-checkbox coverage. B3 was merged atf1600ed0before the hold and B1 reuses itstask_ops::verify_target.b91d8ab0bec85e00cargo fmt --all --checkat981f6c25cargo clippy --workspace --all-targets -j4 -- -D warningsat981f6c25UPDATE_CONTRACTS=1 cargo test -j4 -p calternal contractpassed; generated snapshot preserved (two Unicode formatting lines)--checknot run before holdfinal full gates remain incomplete. conservative pending-conflict recovery in this preserved implementation refuses the room until its exact pre/post image is restored. this is work in progress for the shared redesign, not a ready-to-merge implementation.
on hold pending the shared Tasks writes v2 plan, PR #808, branch
docs/tasks-writes-v2-plan, head8d32f656049061a195653e950c9db097d10285c7.docs/plans/0066-tasks-writes-v2.mdcovers all task writes: pure exact-byte splice planners plus ONE journaled executor for apply, recovery and recorded inverse undo, reusing calendar v2’s parsed view and frontmatter writer. Undo requires a committed change and the exact recorded post-image; refused removals cannot be restored. Executor first, then B1, B2, B3. Keep existing work/probes preserved; no further patch/review loop or merge of this held implementation pending the plan. Docs only; no implementation started.Closing: superseded by #812 (merged into dev) (named in the PR body or comments). Branch kept.
Pull request closed