Sync taskledger state across PCs

Taskledger stores durable state below the Ledgercore-resolved data mount. The default mount is external storage at ../ledger; local overrides may select user-data. Rebuildable indexes are always resolved as cache storage.

Schema-3 project state

The canonical layout is:

/home/me/src/project-a/.ledger/ledger.toml
/home/me/src/project-a/.ledger/taskledger/config.toml
/home/me/src/ledger/taskledger/<project-uuid>/data
<user-cache>/taskledger/<project-uuid>/<checkout>/indexes

Initialize and inspect the resolved mounts explicitly:

taskledger init
taskledger storage where
taskledger storage path data
taskledger storage path indexes
taskledger storage set data user-data --scope local
# Use `taskledger migrate` for data relocation; `storage set` changes topology only.

The project UUID and Ledgercore binding keep shared projects isolated.

Shared state Git repo

The sibling store can be an explicit Git repository. Taskledger Git sync derives the repository root and limits canonical operations to the resolved project path:

taskledger sync git init
taskledger sync git status
taskledger sync git pull
taskledger sync git push

Second PC bootstrap

Indexes are checkout-local derived state and are not synchronized between PCs. After opening a project on a new machine, deleting the local cache, or allowing the cache to be evicted, read-only commands continue to use canonical records. The first mutating command creates the local Ledgercore cache binding and rebuilds the indexes automatically; no second taskledger init is required. If a non-empty unbound cache is found, Taskledger preserves it as an indexes.quarantine-* sibling before rebuilding. Use taskledger repair index for explicit cache health repair.

Clone both repositories as siblings:

cd ~/src
git clone <source-repo-url> project-a
git clone <private-state-repo-url> taskledger-state

cd project-a
taskledger info
taskledger doctor
taskledger task list

Daily sync protocol

Taskledger provides a Git sync command group that supports this workflow:

taskledger sync git init --repo ../taskledger-state --project-path project-a
taskledger sync git status
taskledger sync git pull
taskledger sync git push
taskledger sync git push --message "Sync project-a taskledger state"

In a shared taskledger-state repository, Taskledger can safely inspect and report project-local vs outside-project dirty paths. sync git push commits repository-wide changes by design to match the standard Git workflow. Use sync git cd for advanced manual inspection or conflict resolution.

Artifact preflight

taskledger sync git push checks Taskledger-owned artifact files before staging or committing. It refuses any existing file over the configured artifact_max_bytes limit and reports the paths, sizes, limit, and taskledger doctor remediation. Plain git push remains outside Taskledger’s control, and Taskledger does not rewrite history or use Git LFS.

For manual conflict resolution or debugging:

cd "$(taskledger sync git cd)"
git status --short

Before starting work on a PC:

cd ~/src/project-a
taskledger sync git status
taskledger sync git pull
taskledger doctor
taskledger next-action

After finishing a task cycle or stopping at a safe boundary:

cd ~/src/project-a
taskledger doctor
taskledger sync git status
taskledger sync git push

Active lock rule

Do not use the same Taskledger state concurrently from multiple PCs. Prefer to switch machines only when:

  • the task is done;

  • the task is approved and no implementation lock exists;

  • implementation is finished and validation has not started; or

  • no active lock is present.

Keep one active writer per project. Concurrent writes can produce Git conflicts or semantic conflicts across canonical task records.

When to use export/import instead

Archive commands are the root-level transfer primitives:

taskledger export task-0040
taskledger import ./taskledger-task-project-a-main-task-0040-...tar.gz
taskledger export --output ./taskledger-transfer.tar.gz
taskledger import ./taskledger-transfer.tar.gz --dry-run

If work must move mid-run, prefer task-scoped transfer archives instead of syncing the full live state directory:

taskledger export task-0040
# copy archive to the other PC
taskledger import ./taskledger-task-project-a-main-task-0040-...tar.gz
taskledger next-action
taskledger implement resume --reason "Continue imported implementation."

Imported runtime locks are quarantined by default, which makes archive transfer safer than syncing an active lock between machines.

Syncthing/rclone caveats

Syncthing and rclone bisync can transport the external state directory, but Git is the safer default for Taskledger’s text-first state because it preserves history and exposes conflicts directly.

If Syncthing is used:

  • avoid concurrent writers;

  • stop one agent before starting another PC;

  • run taskledger doctor after sync; and

  • resolve conflict files before continuing.

Treat rclone bisync as an advanced workflow. Keep Git push/pull under user control and do not automate network sync from Taskledger itself.

Task-centered traceability

Taskledger owns temporal work truth: task history, plans, acceptance criteria, implementation changes, validation checks, reviews, locks, and handoffs. Cross-ledger links are opaque file or ID references.

Use taskledger trace TASK --format json to emit a read-only taskledger.trace.v1 task bundle. The bundle links task IDs, accepted AC IDs, opaque link refs, source refs, evidence refs, changes, reviews, and handoffs.

Evidence import is explicit and auditable through taskledger validate check --criterion ... --status ... --evidence ....

Canonical mounts

Canonical state sync includes the durable data mount by default. runtime, logs, and cache indexes are excluded from application-source sync; indexes can be deleted and rebuilt from data. An explicit audit policy may include selected logs. Workspace, user-data, and cache roots are resolved by Ledgercore and are not changed by taskledger storage move.