Repository navigation
fix(sync): list autosync writes by subcommand - #220
Merged
Merged
Conversation
blocked-by, depends-on, focus, unfocus, and the list, show, and current subcommands of board, epic, task, and ws write nothing that syncs, so they no longer push and pull after they run. defer, due, and note's subcommands that write now sync after they run. A test fails when one of these parents gains a subcommand that is not classified. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to #219, covering the cases its "Not in this PR" section listed except
td dep <id>(see below), plus the reverse problem. The post-run autosync, a push and pull after a command, runs when the command matches the mutating-command list. Two kinds of mismatch remained.Commands that write nothing that syncs, but still synced after they ran:
blocked-byanddepends-on, which only read.focusandunfocus, which only writesession_state. That table doesn't sync.board,epic,task, andws, which matched through their parent's name:board list,board show,epic list,task list,ws current,ws list, andws show.Commands that write but did not sync after they ran. By default, their changes waited for the next td command's startup sync:
deferanddue, which update issues.note's subcommands that write. Note events go toaction_logand push when thesync_notesfeature is on, which it is by default.Changes:
blocked-by,depends-on,focus, andunfocusfrom the list.board,epic,task, andwswith full paths for just their subcommands that write, using fix(sync): stop autosyncing after td comments listings #219's full-path matching.defer,due, andnote's add, archive, delete, edit, pin, restore, unarchive, and unpin subcommands.TestSubcommandsAreClassified. It walks the subcommands ofboard,comments,epic,note,task, andwsthroughisMutatingInvocation. It fails when one is mutating but on the test's read-only list, or neither. A new subcommand of one of these parents fails the test until someone classifies it, which addresses the maintenance cost fix(sync): stop autosyncing after td comments listings #219 named.TestMutationHookRunsOnlyForMutatingCommandsnow clearsTD_SYNC_AUTOandTD_FEATURE_SYNC_AUTOSYNC. Either one set to false in the environment used to fail it under plaingo test;make testalready unsetsTD_FEATURE_SYNC_AUTOSYNC.The "configured for sync but autosync is off" warning follows the same classification, so the commands that stop syncing also stop printing it, and
defer,due, and note writes now can. Startup sync is unchanged. Removing the longest keys made gofmt realign the remaining one-word entries, so the diff ofcmd/autosync.gois easier to read with whitespace hidden.Testing
make test,go vet ./..., andgofmtpass. golangci-lint v2.13.1 withGOOS=linuxand Go 1.27.0, as in CI, reports 0 issues.go test -race -count=1 -run 'Mutat|Classified|AutoSync|Autosync' ./cmd/passes.Tests, all of which fail with
main's list:TestIsMutatingCommandandTestIsMutatingInvocationcover examples of the new reads and writes. The second resolves real invocations throughrootCmd.TestMutationHookRunsOnlyForMutatingCommands, renamed from fix(sync): stop autosyncing after td comments listings #219'sTestMutationHookSkipsCommentsListing, now also runs the hook forboard list,board create,blocked-by,due, andnote add.TestSubcommandsAreClassified, described above. It also fails if a parent key such aswsis added back.Manual: real binaries in the e2e harness, with autosync on and
on_startoff, so each count is the post-run sync alone. Each read-only command ran with nothing pending; with changes pending,mainalso pushes them. Nothing was pending at the end of either run.mainboard list,board show,epic list,task list,blocked-by,depends-on,focus,unfocus,ws current,ws list,ws shownote add,defer,dueboard create,ws startnote list,note showNot in this PR
td dep <id>with one argument (with or without--blocking),td undo --list,td import --dry-run, andtd unstart --sessionor--stalewithout--force. The list can't express those. The command itself would have to tell the post-run hook that it wrote nothing.monitorstays mutating, since you can edit from inside it.initalso writes nothing that syncs. A new project has no sync state, so it never autosyncs. Re-running it in a linked project stops at ".todos/ already exists" and then autosyncs. I left it listed to keep this change to the cases above.sync_notesoff, the pending-event count still includes note events, though push skips them and they stay pending. After this change, a note write printsWarning: sync: N local change(s) not yet pushed to remote (will retry on next td command). Onmain, the next command that autosynced printed the same warning, so the count was already wrong; this change only shows it sooner. I confirmed both in the e2e harness withTD_FEATURE_SYNC_NOTES=false. Excluding those events from the count seemed better as its own change.🤖 Generated with Claude Code