task-agent 1.3.11__tar.gz → 1.3.12__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. {task_agent-1.3.11 → task_agent-1.3.12}/PKG-INFO +1 -1
  2. {task_agent-1.3.11 → task_agent-1.3.12}/docs/README.md +2 -0
  3. task_agent-1.3.12/docs/adr/0001-sync-task-stores-with-an-operation-log.md +121 -0
  4. {task_agent-1.3.11 → task_agent-1.3.12}/docs/architecture/README.md +2 -0
  5. {task_agent-1.3.11 → task_agent-1.3.12}/pyproject.toml +1 -1
  6. task_agent-1.3.12/src/taskagent/chat/last_used.py +531 -0
  7. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/cli.py +262 -13
  8. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/manager.py +150 -2
  9. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/mcp.py +32 -4
  10. task_agent-1.3.12/src/taskagent/oplog.py +289 -0
  11. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/store_registry.py +52 -2
  12. task_agent-1.3.12/src/taskagent/store_sync.py +441 -0
  13. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_chat_last_used.py +87 -0
  14. task_agent-1.3.12/tests/test_oplog.py +220 -0
  15. task_agent-1.3.12/tests/test_store_sync.py +306 -0
  16. task_agent-1.3.12/tests/test_wsl_paths.py +31 -0
  17. {task_agent-1.3.11 → task_agent-1.3.12}/uv.lock +5 -5
  18. task_agent-1.3.11/src/taskagent/chat/last_used.py +0 -255
  19. {task_agent-1.3.11 → task_agent-1.3.12}/.agents/skills/next/SKILL.md +0 -0
  20. {task_agent-1.3.11 → task_agent-1.3.12}/.gemini/settings.json +0 -0
  21. {task_agent-1.3.11 → task_agent-1.3.12}/.github/workflows/ci.yml +0 -0
  22. {task_agent-1.3.11 → task_agent-1.3.12}/.github/workflows/publish.yml +0 -0
  23. {task_agent-1.3.11 → task_agent-1.3.12}/.gitignore +0 -0
  24. {task_agent-1.3.11 → task_agent-1.3.12}/.mise.toml +0 -0
  25. {task_agent-1.3.11 → task_agent-1.3.12}/.pre-commit-config.yaml +0 -0
  26. {task_agent-1.3.11 → task_agent-1.3.12}/.python-version +0 -0
  27. {task_agent-1.3.11 → task_agent-1.3.12}/.ta/agents/agy-cli/meta.toml +0 -0
  28. {task_agent-1.3.11 → task_agent-1.3.12}/.ta/agents/antigravity/meta.toml +0 -0
  29. {task_agent-1.3.11 → task_agent-1.3.12}/.ta/agents/gh/meta.toml +0 -0
  30. {task_agent-1.3.11 → task_agent-1.3.12}/.ta/agents/minimal/meta.toml +0 -0
  31. {task_agent-1.3.11 → task_agent-1.3.12}/.ta/agents/uat-aws/meta.toml +0 -0
  32. {task_agent-1.3.11 → task_agent-1.3.12}/.ta/worker +0 -0
  33. {task_agent-1.3.11 → task_agent-1.3.12}/.ta-config.json +0 -0
  34. {task_agent-1.3.11 → task_agent-1.3.12}/CLAUDE.md +0 -0
  35. {task_agent-1.3.11 → task_agent-1.3.12}/GEMINI.md +0 -0
  36. {task_agent-1.3.11 → task_agent-1.3.12}/Makefile +0 -0
  37. {task_agent-1.3.11 → task_agent-1.3.12}/README.md +0 -0
  38. {task_agent-1.3.11 → task_agent-1.3.12}/agent.env +0 -0
  39. {task_agent-1.3.11 → task_agent-1.3.12}/docs/STATION-MAP.md +0 -0
  40. {task_agent-1.3.11 → task_agent-1.3.12}/docs/chats/gemini-conversation-1773283034591.json +0 -0
  41. {task_agent-1.3.11 → task_agent-1.3.12}/docs/chats/project-init-to-v0.1.46.md +0 -0
  42. {task_agent-1.3.11 → task_agent-1.3.12}/docs/cli/README.md +0 -0
  43. {task_agent-1.3.11 → task_agent-1.3.12}/docs/development/README.md +0 -0
  44. {task_agent-1.3.11 → task_agent-1.3.12}/docs/task-agents.md +0 -0
  45. {task_agent-1.3.11 → task_agent-1.3.12}/docs/workflow/README.md +0 -0
  46. {task_agent-1.3.11 → task_agent-1.3.12}/docs/workflow/trivial_worker_policy.md +0 -0
  47. {task_agent-1.3.11 → task_agent-1.3.12}/opencode.json +0 -0
  48. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/.gemini-plugin/plugin.json +0 -0
  49. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/.mcp.json +0 -0
  50. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/README.md +0 -0
  51. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/hooks/hooks.json +0 -0
  52. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/hooks/session_start.sh +0 -0
  53. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/rules/task_agent.md +0 -0
  54. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/scripts/statusline.sh +0 -0
  55. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/skills/README.md +0 -0
  56. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/skills/agent-import/SKILL.md +0 -0
  57. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/skills/complete-task/SKILL.md +0 -0
  58. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/skills/mission-workflow/SKILL.md +0 -0
  59. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/skills/next/SKILL.md +0 -0
  60. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/antigravity/skills/next-task/SKILL.md +0 -0
  61. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  62. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/.mcp.json +0 -0
  63. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/README.md +0 -0
  64. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/hooks/hooks.json +0 -0
  65. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/hooks/session_start.sh +0 -0
  66. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/scripts/statusline.sh +0 -0
  67. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/skills/agent-import/SKILL.md +0 -0
  68. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/skills/complete-task/SKILL.md +0 -0
  69. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/skills/mission-workflow/SKILL.md +0 -0
  70. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/claude-code/skills/next-task/SKILL.md +0 -0
  71. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/codex/.mcp.json +0 -0
  72. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/codex/README.md +0 -0
  73. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/copilot/.mcp.json +0 -0
  74. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/copilot/README.md +0 -0
  75. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/grok/.mcp.json +0 -0
  76. {task_agent-1.3.11 → task_agent-1.3.12}/plugins/grok/README.md +0 -0
  77. {task_agent-1.3.11 → task_agent-1.3.12}/scripts/check_task_worktree_cleanup.py +0 -0
  78. {task_agent-1.3.11 → task_agent-1.3.12}/scripts/clean_duplicates.py +0 -0
  79. {task_agent-1.3.11 → task_agent-1.3.12}/scripts/migrate_tasks.py +0 -0
  80. {task_agent-1.3.11 → task_agent-1.3.12}/scripts/recover_dates.py +0 -0
  81. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/.env.example +0 -0
  82. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/README.md +0 -0
  83. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/instructions/manager.md +0 -0
  84. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/instructions/validator.md +0 -0
  85. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/instructions/worker.md +0 -0
  86. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/profiles/default.json +0 -0
  87. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/pyproject.toml +0 -0
  88. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/uv.lock +0 -0
  89. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/adk-worker/worker.py +0 -0
  90. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/keet-bridge/README.md +0 -0
  91. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/keet-bridge/bridge.js +0 -0
  92. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/keet-bridge/package-lock.json +0 -0
  93. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/keet-bridge/package.json +0 -0
  94. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/keet-bridge/run.sh +0 -0
  95. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/keet-bridge/test-e2e.js +0 -0
  96. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/matrix-bridge/README.md +0 -0
  97. {task_agent-1.3.11 → task_agent-1.3.12}/sidecars/matrix-bridge/matrix_bridge.py +0 -0
  98. {task_agent-1.3.11 → task_agent-1.3.12}/skills/README.md +0 -0
  99. {task_agent-1.3.11 → task_agent-1.3.12}/skills/agent-import/SKILL.md +0 -0
  100. {task_agent-1.3.11 → task_agent-1.3.12}/skills/complete-task/SKILL.md +0 -0
  101. {task_agent-1.3.11 → task_agent-1.3.12}/skills/mission-workflow/SKILL.md +0 -0
  102. {task_agent-1.3.11 → task_agent-1.3.12}/skills/next/SKILL.md +0 -0
  103. {task_agent-1.3.11 → task_agent-1.3.12}/skills/next-task/SKILL.md +0 -0
  104. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/__init__.py +0 -0
  105. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/__main__.py +0 -0
  106. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/agent.py +0 -0
  107. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/agent_registry.py +0 -0
  108. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/audit.py +0 -0
  109. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/chat/__init__.py +0 -0
  110. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/chat/config.py +0 -0
  111. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/chat/discovery.py +0 -0
  112. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/config.py +0 -0
  113. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/discovery.py +0 -0
  114. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/importers/__init__.py +0 -0
  115. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/importers/antigravity.py +0 -0
  116. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/importers/base.py +0 -0
  117. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/importers/claude_code.py +0 -0
  118. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/importers/generic.py +0 -0
  119. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/inbox.py +0 -0
  120. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/models/__init__.py +0 -0
  121. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/models/issue.py +0 -0
  122. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/models/metric.py +0 -0
  123. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/perf.py +0 -0
  124. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/plugins/__init__.py +0 -0
  125. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/plugins/github.py +0 -0
  126. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/runner.py +0 -0
  127. {task_agent-1.3.11 → task_agent-1.3.12}/src/taskagent/templates.py +0 -0
  128. {task_agent-1.3.11 → task_agent-1.3.12}/test-dir/opencode.json +0 -0
  129. {task_agent-1.3.11 → task_agent-1.3.12}/tests/conftest.py +0 -0
  130. {task_agent-1.3.11 → task_agent-1.3.12}/tests/e2e/test_agent_sandboxing.sh +0 -0
  131. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_agent.py +0 -0
  132. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_agent_registry.py +0 -0
  133. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_agy_cli_worker.py +0 -0
  134. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_atomic_mutations.py +0 -0
  135. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_auto_commit.py +0 -0
  136. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_chat_config.py +0 -0
  137. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_chat_discovery.py +0 -0
  138. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_cli.py +0 -0
  139. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_cli_windows.py +0 -0
  140. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_discovery.py +0 -0
  141. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_github_token.py +0 -0
  142. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_importers.py +0 -0
  143. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_inbox.py +0 -0
  144. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_inbox_watch.py +0 -0
  145. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_lease.py +0 -0
  146. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_manager.py +0 -0
  147. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_manager_git.py +0 -0
  148. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_mcp.py +0 -0
  149. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_metrics.py +0 -0
  150. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_migration.py +0 -0
  151. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_perf.py +0 -0
  152. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_plugin_antigravity.py +0 -0
  153. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_plugin_claude.py +0 -0
  154. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_project_host_root.py +0 -0
  155. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_rebind.py +0 -0
  156. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_remote_attach.py +0 -0
  157. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_remote_create.py +0 -0
  158. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_repo_resolve.py +0 -0
  159. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_runner.py +0 -0
  160. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_store_registry.py +0 -0
  161. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_store_symlink.py +0 -0
  162. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_templates.py +0 -0
  163. {task_agent-1.3.11 → task_agent-1.3.12}/tests/test_yazi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: task-agent
3
- Version: 1.3.11
3
+ Version: 1.3.12
4
4
  Summary: A prioritized, file-based task queue for autonomous agentic workers
5
5
  Project-URL: Homepage, https://github.com/InTEGr8or/task-agent
6
6
  Project-URL: Repository, https://github.com/InTEGr8or/task-agent.git
@@ -14,6 +14,8 @@ Welcome to the comprehensive documentation for **Task Agent**, a prioritized, fi
14
14
  - Information on project setup, testing, and release processes.
15
15
  - [**Station Map**](./STATION-MAP.md)
16
16
  - Formal declaration of task-agent as a typed file-path station system: stations, transitions, edge roles, and conformance gaps.
17
+ - [**ADR 0001: store sync**](./adr/0001-sync-task-stores-with-an-operation-log.md)
18
+ - Git carries an append-only per-writer operation log. The station tree is a projection.
17
19
 
18
20
  ## 🚀 Quick Start
19
21
 
@@ -0,0 +1,121 @@
1
+ # ADR 0001: Sync task stores with an append-only operation log
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-10-29
5
+ - Scope: task-agent station stores, their `*-tasks` git remotes, native Windows clients, and handterm `ta`
6
+
7
+ ## Context
8
+
9
+ A task store is a typed path queue. Stations (`pending/`, `draft/`, `active/`, `completed/`, `deleted/`) hold one directory per slug. `mission.usv` is the priority index. Leases live in `lease.json`. The inbox is same-machine only.
10
+
11
+ Each durable store is already its own git repo under the machine data root (`TA_DATA_ROOT`, else `$XDG_DATA_HOME/task-agent`, else `~/.local/share/task-agent`). The subject repo stays separate. GitHub sibling repos are the remotes, for example `InTEGr8or/task-agent-tasks` and `bizkite-co/handterm-tasks`. `ta store remote {suggest,create,set,attach}` configures that remote. Mutations commit locally through `_commit_task_store`. They do not push. There is no `ta store pull` and no `ta store clone`.
12
+
13
+ That layout is the right archive. It is a weak multi-writer database.
14
+
15
+ - WSL and native Windows use different home directories. `ta store migrate` is refused on native Windows because of that split and because git often materializes symlinks as text files. A PowerShell client cannot replay the WSL migration.
16
+ - Two clones of one store on one PC diverge even when a remote exists. This machine's `task-agent-tasks` history had already moved past the GitHub `main` tip.
17
+ - The hot files are `mission.usv` and directory renames. Overlapping edits do not merge. `git pull --rebase` before every push stops the worker on the first conflict.
18
+ - handterm `ta` already targets `bizkite-co/handterm-tasks` through the GitHub Contents API. It writes a single markdown file, does not update `mission.usv`, and leaves the pending copy in place when it marks a task active. A phone cannot join a rebase.
19
+
20
+ Workers that must keep working are: WSL `ta`, a Windows client of the same PC, other machines, and handterm on a device that only has HTTPS.
21
+
22
+ ## Decision
23
+
24
+ Git remains the transport and the history log. The replicated object is an append-only operation log. The station tree and `mission.usv` are a projection of that log.
25
+
26
+ ### Log shape
27
+
28
+ Ops live inside the store:
29
+
30
+ ```text
31
+ .task-agent/ops/<writer-id>/<op-id>.op.json
32
+ ```
33
+
34
+ `<writer-id>` is one id per machine, stored at `<data-root>/writer-id` (override with `TA_WRITER_ID`). A writer appends only under its own directory. Sync unions every writer's files. Apply order is `(at, id)` with UTC timestamps. A hybrid logical clock can replace that sort later without moving the files.
35
+
36
+ Each file is one JSON object:
37
+
38
+ | Field | Meaning |
39
+ | :--- | :--- |
40
+ | `v` | Schema version. `1` for this ADR. |
41
+ | `id` | Unique, time-prefixed id. |
42
+ | `writer` | Machine writer id. |
43
+ | `at` | UTC timestamp. |
44
+ | `verb` | `create`, `move`, `edges`, `rename`, `lease`, `release`. |
45
+ | `slug` | Task slug the verb applies to. |
46
+ | `payload` | Verb fields. `create` carries `name` and `station`. `move` carries `station` and `from_station`. `edges` carries `blocked_by` and `subtask_of`. `rename` carries `new_slug`. |
47
+
48
+ Rules for version 1:
49
+
50
+ - The first `create` for a slug wins. A second `create` for the same slug is a no-op.
51
+ - A later `move` for the same slug wins.
52
+ - `edges` replaces the fields it names.
53
+ - Task markdown still rides in the same commit as the op while `ta` is the writer. A client with no working tree (handterm) puts the new task body in the `create` payload so a materializer can write the file.
54
+ - `ingest` is not an op. Adoption of loose markdown stays a local repair, not a sync verb.
55
+
56
+ ### Same machine
57
+
58
+ The data root stays on the WSL Linux filesystem (`~/.local/share/task-agent`). Do not point `TA_DATA_ROOT` at `/mnt/c` or `%LOCALAPPDATA%`. That creates a second store on NTFS and splits the registry.
59
+
60
+ Windows PowerShell sets one variable, from `ta store data-root --windows`:
61
+
62
+ ```text
63
+ TA_DATA_ROOT=\\wsl$\Debian\home\<user>\.local\share\task-agent
64
+ ```
65
+
66
+ That UNC is the same directory, not a copy. Code repos may stay on `C:\`. `ta store migrate` run from WSL moves an in-repo `.task-agent/tasks` tree into the Linux data root and records both `/mnt/c/...` and `C:\...` as host paths. There is no gate that blocks `ta` until every repo is migrated. Migrate the checkout you are using. Windows does not run `ta store migrate`.
67
+
68
+ ### Other machines and the phone
69
+
70
+ `ta sync` (not built yet) pulls the `*-tasks` repo, unions the log, rebuilds `mission.usv` and station moves from the projection, and pushes. Ordinary mutations keep appending ops and committing the projection so current agents still read directories.
71
+
72
+ handterm `ta`, defaulting to the subject repo's sibling `*-tasks` repo (`handterm` unless `--repo` is set), appends one op with the Git Data API. The branch update compare-and-swaps the expected SHA and retries once. It does not edit `mission.usv` itself.
73
+
74
+ A sequencer HTTP service may later assign order and fan the same log out. The file format does not change if that service appears. GitHub stays a valid relay until then.
75
+
76
+ ## Consequences
77
+
78
+ - Concurrent creates of different slugs merge by taking both files.
79
+ - Two moves of one slug have a defined winner (later op id) instead of a rebase conflict in `mission.usv`.
80
+ - The projection can be rebuilt from the log. Until `ta sync` exists, the committed tree is still what `ta next` reads, and the log is written beside it.
81
+ - Clock skew can reorder ops across machines. Acceptable for v1 because ids are the only cross-writer order. A logical clock is a follow-on, not a new store.
82
+ - Writers must not edit another writer's op directory. Git should not present those files as modify/modify conflicts.
83
+ - Existing stores gain ops on the next mutation. Old history is not backfilled.
84
+
85
+ ## Rejected strategies
86
+
87
+ ### Push the materialized tree after every change
88
+
89
+ Commits already happen. Adding `git push` after `_commit_task_store`, with or without `git pull --rebase`, publishes the projection. The second writer to touch `mission.usv` or rename the same slug loses or stops. handterm's one-file Contents API cannot rebase. Useful only as a one-time backup of a store that has no log yet.
90
+
91
+ ### Two clones on one PC, synced only through GitHub
92
+
93
+ This is the failure already seen when a centralized store and an ejected copy both stayed writable. Shared `TA_DATA_ROOT` removes the need to sync that pair.
94
+
95
+ ### GitHub Issues as the queue
96
+
97
+ `ta github sync` is a separate, unfinished, one-way import. Issues have no station paths, no `mission.usv` order, and no leases. Mirroring there would be a third queue.
98
+
99
+ ### GitHub Wiki, Keet, or Matrix as the store
100
+
101
+ The wiki was rejected as a product path when sibling `*-tasks` repos were chosen. Keet and Matrix rooms configured on a store are notification channels. They are not a file log and not a branch with compare-and-swap.
102
+
103
+ ### CRDT database or hosted SQL sync instead of the file checkout
104
+
105
+ Automerge, Yjs, ElectricSQL, Turso, and similar systems solve multi-writer sync by replacing the working copy. Agents and `ta` read station directories. The station map is a typed path queue. Putting a list CRDT under the op log is possible later for reorder. Replacing the tree with a hosted database drops the checkout those workers use.
106
+
107
+ ### A bespoke sequencer as the only writer, now
108
+
109
+ One online API that sequences every transition is a good relay once the phone and several agents are always connected. Offline `ta` would become a client of that service. The op log gets the same ordering rules and still moves through git. The sequencer can be added in front of the log. It is not a reason to pick a different replicated object.
110
+
111
+ ## Implementation status
112
+
113
+ Accepted and in progress on the task "Sync task stores with an append-only operation log".
114
+
115
+ | Slice | State |
116
+ | :--- | :--- |
117
+ | This ADR | Accepted |
118
+ | Append ops from store mutations, plus an in-memory reduce | In `src/taskagent/oplog.py` |
119
+ | `ta store sync` | Fast-forward or merge, then replay ops onto the tree and push. A successful store commit runs this when the store has `origin` and that git root is the store itself. A store inside a subject checkout is committed locally and not pushed. `TA_NO_AUTO_SYNC=1` skips the sync. A fetch, merge, or push failure keeps the local commit and aborts a half-finished merge. |
120
+ | handterm `ta new` | One `create` op plus the task file, via `commit-repo-files` (Git Data API, fast-forward ref update, one retry). The Lambda route has to be deployed before a phone can call it. |
121
+ | One-time publish | `ta store sync` pushes when the local store is a fast-forward of GitHub. |
@@ -2,6 +2,8 @@
2
2
 
3
3
  Task Agent is designed with a "filesystem-as-a-database" philosophy. This ensures that the task queue is highly portable, version-controlled by git, and easily readable by both humans and machines.
4
4
 
5
+ Multi-writer sync of a store is an append-only operation log under `.task-agent/ops/<writer-id>/`. Git transports that log. `mission.usv` and the station directories are a projection. See [ADR 0001](../adr/0001-sync-task-stores-with-an-operation-log.md).
6
+
5
7
  ## 📂 Data Storage
6
8
 
7
9
  All task data is stored within the `docs/tasks/` directory.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "task-agent"
3
- version = "1.3.11"
3
+ version = "1.3.12"
4
4
  description = "A prioritized, file-based task queue for autonomous agentic workers"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"