trekoon 0.4.1 → 0.4.3

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 (58) hide show
  1. package/.agents/skills/trekoon/SKILL.md +97 -765
  2. package/.agents/skills/trekoon/reference/execution-with-team.md +91 -141
  3. package/.agents/skills/trekoon/reference/execution.md +188 -159
  4. package/.agents/skills/trekoon/reference/harness-primitives.md +77 -0
  5. package/.agents/skills/trekoon/reference/planning.md +213 -213
  6. package/.agents/skills/trekoon/reference/status-machine.md +21 -0
  7. package/.agents/skills/trekoon/reference/sync.md +82 -0
  8. package/README.md +29 -8
  9. package/docs/ai-agents.md +65 -6
  10. package/docs/commands.md +149 -5
  11. package/docs/machine-contracts.md +123 -0
  12. package/docs/quickstart.md +55 -3
  13. package/package.json +1 -1
  14. package/src/board/assets/app.js +47 -13
  15. package/src/board/assets/components/Component.js +20 -8
  16. package/src/board/assets/components/Workspace.js +9 -3
  17. package/src/board/assets/components/helpers.js +4 -0
  18. package/src/board/assets/runtime/delegation.js +8 -0
  19. package/src/board/assets/runtime/focus-trap.js +48 -0
  20. package/src/board/assets/state/actions.js +45 -4
  21. package/src/board/assets/state/api.js +304 -17
  22. package/src/board/assets/state/store.js +82 -11
  23. package/src/board/assets/state/url.js +10 -0
  24. package/src/board/assets/state/utils.js +2 -1
  25. package/src/board/event-bus.ts +81 -0
  26. package/src/board/routes.ts +430 -40
  27. package/src/board/server.ts +86 -10
  28. package/src/board/snapshot.ts +6 -0
  29. package/src/board/wal-watcher.ts +313 -0
  30. package/src/commands/board.ts +52 -17
  31. package/src/commands/epic.ts +7 -9
  32. package/src/commands/error-utils.ts +54 -1
  33. package/src/commands/help.ts +75 -10
  34. package/src/commands/migrate.ts +153 -24
  35. package/src/commands/quickstart.ts +7 -0
  36. package/src/commands/skills.ts +17 -5
  37. package/src/commands/subtask.ts +71 -10
  38. package/src/commands/suggest.ts +6 -13
  39. package/src/commands/task.ts +137 -88
  40. package/src/domain/batch-validation.ts +329 -0
  41. package/src/domain/cascade-planner.ts +412 -0
  42. package/src/domain/dependency-rules.ts +15 -0
  43. package/src/domain/mutation-service.ts +842 -187
  44. package/src/domain/search.ts +113 -0
  45. package/src/domain/tracker-domain.ts +167 -693
  46. package/src/domain/types.ts +56 -2
  47. package/src/export/render-markdown.ts +1 -2
  48. package/src/index.ts +37 -0
  49. package/src/runtime/cli-shell.ts +44 -0
  50. package/src/runtime/daemon.ts +700 -0
  51. package/src/storage/backup.ts +166 -0
  52. package/src/storage/database.ts +268 -4
  53. package/src/storage/migrations.ts +441 -22
  54. package/src/storage/path.ts +8 -0
  55. package/src/storage/schema.ts +5 -1
  56. package/src/sync/event-writes.ts +38 -11
  57. package/src/sync/git-context.ts +226 -8
  58. package/src/sync/service.ts +679 -156
package/README.md CHANGED
@@ -90,8 +90,8 @@ What the agent does during execution:
90
90
  calls `task done`
91
91
  6. `task done` returns which downstream tasks just became unblocked, so the
92
92
  orchestrator knows what to dispatch next
93
- 7. After all tasks complete: code review, tests, manual verification, then marks
94
- the epic `done`
93
+ 7. After all tasks complete: review agent or review skill for non-trivial
94
+ changes, tests, manual verification, then marks the epic `done`
95
95
 
96
96
  The orchestrator uses `task done` responses to drive the whole loop. No polling,
97
97
  no guessing. When a task finishes, Trekoon tells you exactly what's ready next.
@@ -110,13 +110,15 @@ agents don't know how to use Trekoon properly.
110
110
  ```bash
111
111
  trekoon skills install # repo-local (.agents/skills/trekoon/)
112
112
  trekoon skills install -g # global (~/.agents/skills/trekoon)
113
+ trekoon skills install --link --editor codex # editor link (.codex/skills/trekoon)
113
114
  trekoon update # refresh all installed skills
114
115
  ```
115
116
 
116
- The skill bundles three reference documents that agents load on demand:
117
+ The skill bundles reference documents that agents load on demand:
117
118
 
118
119
  | Agent needs to... | Skill reads | What it covers |
119
120
  | --- | --- | --- |
121
+ | Coordinate across harnesses | `reference/harness-primitives.md` | Universal subagent, question, local task display, review, and evidence-recording guidance |
120
122
  | Plan a feature | `reference/planning.md` | Decomposition, writing standard, dependency modeling, validation |
121
123
  | Execute an epic | `reference/execution.md` | Graph building, lane grouping, sub-agent dispatch, verification (universal) |
122
124
  | Execute with Agent Teams | `reference/execution-with-team.md` | TeamCreate/SendMessage, parallel Claude Code instances in tmux |
@@ -145,6 +147,16 @@ Execute only:
145
147
  /trekoon <epic-id> execute
146
148
  ```
147
149
 
150
+ When you execute an epic, use subagents by default for any meaningful work that
151
+ can run independently. Keep small or tightly coupled tasks in the parent agent.
152
+ Use the main context for orchestration, dependency decisions, user
153
+ communication, and final synthesis while Trekoon remains the durable source of
154
+ truth.
155
+
156
+ If a harness has a higher-priority rule requiring explicit permission before
157
+ subagents, surface that immediately instead of silently doing broad work
158
+ yourself.
159
+
148
160
  Plan and execute end to end:
149
161
 
150
162
  ```
@@ -154,9 +166,11 @@ dependency order until the epic is complete
154
166
 
155
167
  ## Agent Teams
156
168
 
157
- For larger epics, Trekoon supports Claude Code Agent Teams. Instead of
158
- sequential sub-agents, you get real parallel Claude Code instances coordinated
159
- through `TeamCreate` and `SendMessage`, each running in its own tmux pane.
169
+ For larger epics, use the current harness's native subagent mechanism for
170
+ meaningful work that can run independently. Claude Code Agent Teams are one
171
+ runtime-specific option: instead of sequential sub-agents, you get real parallel
172
+ Claude Code instances coordinated through `TeamCreate` and `SendMessage`, each
173
+ running in its own tmux pane.
160
174
 
161
175
  Requires Claude Code env variable `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=true`.
162
176
 
@@ -191,7 +205,9 @@ trekoon board update # refresh assets only
191
205
  ```
192
206
 
193
207
  Binds to `127.0.0.1` only with a per-session token. Gives you an epics
194
- overview, kanban workspace per epic, task detail modals, and search.
208
+ overview, kanban workspace per epic, task detail modals, and search. The board
209
+ client subscribes to `/api/snapshot/stream` (SSE), so mutations from another
210
+ shell, worktree, or browser tab show up live without a manual refresh.
195
211
 
196
212
  ## Commands
197
213
 
@@ -199,15 +215,20 @@ overview, kanban workspace per epic, task detail modals, and search.
199
215
  | --- | --- |
200
216
  | Set up a repo | `trekoon init` |
201
217
  | Open the local board | `trekoon board open` |
202
- | Plan work | `trekoon epic create ...`, `trekoon epic expand ...` |
218
+ | Plan work | `trekoon --toon epic create ...`, `trekoon --toon epic expand ...` |
203
219
  | Create tasks in bulk | `trekoon task create-many ...` |
204
220
  | Add dependencies | `trekoon dep add-many ...` |
205
221
  | Start an agent session | `trekoon session --epic <id>` |
206
222
  | Get next-action suggestions | `trekoon suggest --epic <id>` |
207
223
  | Check epic progress | `trekoon epic progress <id>` |
208
224
  | Export epic to Markdown | `trekoon epic export <id>` |
225
+ | Claim a task atomically | `trekoon task claim <id> --owner <owner>` |
226
+ | Claim a subtask atomically | `trekoon subtask claim <id> --owner <owner>` |
209
227
  | Mark a task done | `trekoon task done <id>` |
210
228
  | Sync across worktrees | `trekoon sync pull --from main` |
229
+ | Back up the DB before migrations | `trekoon migrate backup` |
230
+ | Reveal full board token | `trekoon board open --reveal-token` |
231
+ | Run experimental daemon | `trekoon serve` (experimental) |
211
232
  | Get help | `trekoon [command] -h` |
212
233
 
213
234
  Every command supports `--toon`, `--json`, `--compact` for structured output.
package/docs/ai-agents.md CHANGED
@@ -14,22 +14,39 @@ agent to:
14
14
  - append progress and blocker notes instead of rewriting descriptions
15
15
  - preview scoped replace before `--apply`
16
16
  - treat `.trekoon` as shared repo-scoped state
17
+ - use harness-local todo/task tools as a live progress display while keeping
18
+ Trekoon as the durable source of truth
19
+ - use subagents by default for meaningful work that can run independently when
20
+ the harness exposes them
21
+ - keep small or tightly coupled tasks in the parent agent so the main context
22
+ stays available for orchestration and decisions
17
23
 
18
24
  The skill ships with reference guides so the agent can handle the full
19
25
  plan-to-completion workflow from one install:
20
26
 
21
27
  ```
22
28
  .agents/skills/trekoon/
23
- SKILL.md <- command reference, status machine, agent loop
29
+ SKILL.md <- command router and operating contract
24
30
  reference/
31
+ harness-primitives.md <- universal agent/task/question/review primitives
25
32
  planning.md <- decomposition, writing standard, validation
26
33
  execution.md <- graph building, lane dispatch, verification
27
34
  execution-with-team.md <- Agent Teams pattern (Claude Code only)
28
35
  ```
29
36
 
30
- The agent loads the relevant reference on demand: `planning.md` when asked to
31
- plan, `execution.md` when asked to execute, `execution-with-team.md` when Agent
32
- Teams are available.
37
+ The command shape determines what the agent loads:
38
+
39
+ | User command | Required references |
40
+ | --- | --- |
41
+ | `/trekoon plan <goal>` | `harness-primitives.md`, then `planning.md` |
42
+ | `/trekoon <id>` | `SKILL.md` only, unless deeper analysis is needed |
43
+ | `/trekoon <id> analyze` | `SKILL.md` plus targeted Trekoon reads |
44
+ | `/trekoon <id> execute` | `harness-primitives.md`, then `execution.md` |
45
+ | `/trekoon <id> team execute` | `harness-primitives.md`, then `execution-with-team.md` |
46
+
47
+ `harness-primitives.md` is loaded before planning or execution because those
48
+ modes may need structured questions, local progress displays, subagent
49
+ delegation, review agents, and runtime-specific orchestration.
33
50
 
34
51
  ## Install the skill
35
52
 
@@ -42,6 +59,7 @@ Create a project-local editor link when your agent environment supports it:
42
59
  ```bash
43
60
  trekoon skills install --link --editor opencode
44
61
  trekoon skills install --link --editor claude
62
+ trekoon skills install --link --editor codex
45
63
  trekoon skills install --link --editor pi
46
64
  trekoon skills install --link --editor opencode --to ./.custom-editor/skills
47
65
  trekoon skills update
@@ -52,6 +70,7 @@ Path behavior:
52
70
  - Canonical install: `.agents/skills/trekoon/SKILL.md`
53
71
  - OpenCode link: `.opencode/skills/trekoon`
54
72
  - Claude link: `.claude/skills/trekoon`
73
+ - Codex link: `.codex/skills/trekoon`
55
74
  - Pi link: `.pi/skills/trekoon`
56
75
  - `--to <path>` changes only the editor link root
57
76
  - `--allow-outside-repo` is for intentional external links
@@ -89,10 +108,25 @@ Typical flow:
89
108
  4. Execute the plan (reads `reference/execution.md` internally)
90
109
  5. Update progress, blockers, and completion state as you go
91
110
 
111
+ > **Experimental — not for routine agent use:** `trekoon serve` and the
112
+ > `--daemon` flag are experimental. Use the default one-shot CLI path for
113
+ > any production or automated agent workflow until daemon mode stabilizes.
114
+
92
115
  ## Default execution loop
93
116
 
94
117
  The core loop: **session, work, task done, repeat**.
95
118
 
119
+ When you execute an epic, use subagents by default for any meaningful work that
120
+ can run independently. Keep small or tightly coupled tasks in the parent agent.
121
+ Build the Trekoon execution graph, group ready tasks into lanes, keep a local
122
+ todo/task display for the user, and synthesize the results. Use the parent
123
+ context for dependency decisions and finishing the epic.
124
+
125
+ Some harnesses have higher-priority rules that require explicit user permission
126
+ before spawning subagents. When that happens, say so immediately after
127
+ discovering independent lanes and ask for permission before broad execution. Do
128
+ not silently default to single-agent execution.
129
+
96
130
  Start with a single orientation call, optionally scoped to an epic:
97
131
 
98
132
  ```bash
@@ -113,14 +147,24 @@ If the session shows you're behind, pull tracker events before claiming work:
113
147
  trekoon --toon sync pull --from main
114
148
  ```
115
149
 
116
- Claim work, assign ownership, then finish or report a block:
150
+ Claim work atomically using SQL compare-and-swap (recommended for parallel
151
+ agents), then finish or report a block:
117
152
 
118
153
  ```bash
119
- trekoon --toon task update <task-id> --status in_progress --owner "agent-1"
154
+ trekoon --toon task claim <task-id> --owner "agent-1"
120
155
  trekoon --toon task done <task-id>
121
156
  trekoon --toon task update <task-id> --append "Blocked by <reason>" --status blocked
122
157
  ```
123
158
 
159
+ `task claim` is the safe primitive for parallel agents. Two concurrent calls on
160
+ the same task return exactly one `claimed: true`. Check `data.claimed` before
161
+ proceeding — if false, another agent won the race.
162
+
163
+ ```bash
164
+ # Fallback: non-atomic claim (single-agent or sequential workflows only)
165
+ trekoon --toon task update <task-id> --status in_progress --owner "agent-1"
166
+ ```
167
+
124
168
  Use `task done` when the task is actually finished. It marks the task complete,
125
169
  auto-transitions through `in_progress` if needed, reports newly unblocked
126
170
  downstream tasks, warns about incomplete subtasks, and returns the next ready
@@ -179,6 +223,20 @@ notes, mark it done, and repeat until there are no ready tasks or you hit a
179
223
  blocker.
180
224
  ```
181
225
 
226
+ ### Execute with subagents where useful
227
+
228
+ ```text
229
+ /trekoon <epic-id> execute -- use subagents by default for meaningful work that
230
+ can run independently, keep Trekoon as the source of truth, and use local task
231
+ tools to show live progress.
232
+ ```
233
+
234
+ Short form for harnesses that require explicit delegation wording:
235
+
236
+ ```text
237
+ /trekoon <epic-id> execute with subagents
238
+ ```
239
+
182
240
  ### Plan and execute end to end
183
241
 
184
242
  ```text
@@ -201,6 +259,7 @@ Use the narrowest command that answers the question:
201
259
  | One task with subtasks | `trekoon --toon task show <task-id> --all` |
202
260
  | One epic tree | `trekoon --toon epic show <epic-id> --all` |
203
261
  | Export epic to Markdown | `trekoon --toon epic export <epic-id>` |
262
+ | Snapshot the DB before manual recovery | `trekoon --toon migrate backup [--retain <n>]` |
204
263
  | Repeated text in one scope | `trekoon --toon epic|task|subtask search ...` |
205
264
 
206
265
  For repeated text changes, use the safe replace loop:
package/docs/commands.md CHANGED
@@ -12,20 +12,21 @@ the quickest way to get started, read [Quickstart](quickstart.md) first.
12
12
  - `trekoon epic <create|expand|list|show|search|replace|update|delete|progress>`
13
13
  - `trekoon session [--epic <epic-id>]`
14
14
  - `trekoon suggest [--epic <epic-id>]`
15
- - `trekoon task <create|create-many|list|show|ready|next|done|search|replace|update|delete>`
16
- - `trekoon subtask <create|create-many|list|search|replace|update|delete>`
15
+ - `trekoon task <create|create-many|list|show|ready|next|done|search|replace|update|delete|claim>`
16
+ - `trekoon subtask <create|create-many|list|search|replace|update|delete|claim>`
17
17
  - `trekoon dep <add|add-many|remove|list|reverse>`
18
18
  - `trekoon events prune [--dry-run] [--archive] [--retention-days <n>]`
19
- - `trekoon migrate <status|rollback> [--to-version <n>]`
19
+ - `trekoon migrate <status|rollback|backup> [--to-version <n>] [--retain <n>]`
20
20
  - `trekoon sync status [--from <branch>]`
21
21
  - `trekoon sync pull --from <branch>`
22
22
  - `trekoon sync resolve <conflict-id> --use ours|theirs [--dry-run]`
23
23
  - `trekoon sync resolve --all --use ours|theirs [--entity <id>] [--field <name>] [--dry-run]`
24
24
  - `trekoon sync conflicts <list|show> [--mode pending|all]`
25
- - `trekoon skills install [--link --editor opencode|claude|pi] [--to <path>] [--allow-outside-repo]`
26
- - `trekoon skills install -g|--global [--editor opencode|claude|pi]`
25
+ - `trekoon skills install [--link --editor opencode|claude|codex|pi] [--to <path>] [--allow-outside-repo]`
26
+ - `trekoon skills install -g|--global [--editor opencode|claude|codex|pi]`
27
27
  - `trekoon skills update`
28
28
  - `trekoon wipe --yes`
29
+ - `trekoon serve` (experimental)
29
30
 
30
31
  ## Global options
31
32
 
@@ -33,6 +34,7 @@ the quickest way to get started, read [Quickstart](quickstart.md) first.
33
34
  - `--toon` — TOON-encoded output (preferred for agent loops)
34
35
  - `--compact` — strips contract metadata from TOON/JSON envelopes
35
36
  - `--compat <mode>` — explicit machine compatibility behavior
37
+ - `--daemon` — (experimental) route the call through a running `trekoon serve` daemon over a Unix socket; transparently falls back to the in-process CLI when no daemon is reachable. Equivalent to `TREKOON_DAEMON=1`.
36
38
  - `--help` — root and command help
37
39
  - `--version` — CLI version
38
40
 
@@ -73,6 +75,7 @@ Board API endpoints (all require token authentication):
73
75
  | Method | Endpoint | Purpose |
74
76
  | --- | --- | --- |
75
77
  | `GET` | `/api/snapshot` | Full board state (epics, tasks, subtasks, deps, counts) |
78
+ | `GET` | `/api/snapshot/stream` | Server-sent events stream of `snapshot` and `snapshotDelta` events for live updates |
76
79
  | `PATCH` | `/api/epics/{id}` | Update epic title, description, or status |
77
80
  | `PATCH` | `/api/tasks/{id}` | Update task title, description, status, or owner |
78
81
  | `PATCH` | `/api/subtasks/{id}` | Update subtask title, description, status, or owner |
@@ -81,6 +84,19 @@ Board API endpoints (all require token authentication):
81
84
  | `POST` | `/api/dependencies` | Add dependency edge (sourceId, dependsOnId) |
82
85
  | `DELETE` | `/api/dependencies?sourceId=...&dependsOnId=...` | Remove dependency |
83
86
 
87
+ **Note:** the SSE auth token rides as a `?token=` query parameter on
88
+ `/api/snapshot/stream` (EventSource cannot set custom headers), so it may
89
+ appear in reverse-proxy access logs; treat access logs as sensitive if the
90
+ board is exposed beyond localhost.
91
+
92
+ Board mutations from any source — board UI, CLI in another shell, or another
93
+ worktree — propagate to every connected client through the SSE stream. The CLI
94
+ side is driven by a WAL-watcher that diffs the snapshot when
95
+ `.trekoon/trekoon.db-wal` changes; in-process mutations publish deltas
96
+ directly. PATCH endpoints accept `If-Match: <updatedAt-ms>` for optimistic
97
+ concurrency: a stale value returns `409` with `currentUpdatedAt`. Missing
98
+ `If-Match` is allowed for back-compat.
99
+
84
100
  Board commands don't accept command-specific options yet. For tests and local
85
101
  development, `TREKOON_BOARD_ASSET_ROOT` overrides the bundled asset source.
86
102
 
@@ -183,6 +199,41 @@ trekoon subtask update <subtask-id> --owner "agent-2"
183
199
 
184
200
  Also accepted on `PATCH /api/tasks/{id}` and `PATCH /api/subtasks/{id}`.
185
201
 
202
+ ## Task claim
203
+
204
+ ```bash
205
+ trekoon task claim <task-id> --owner <owner>
206
+ trekoon subtask claim <subtask-id> --owner <owner>
207
+ ```
208
+
209
+ Atomically claim a task (or subtask) using a SQL compare-and-swap. Sets
210
+ `status=in_progress` and `owner=<owner>` only when:
211
+
212
+ - The task is in `todo` or `blocked` status, **and**
213
+ - The `owner` column is `NULL` or already equal to `<owner>` (re-entrant claim)
214
+
215
+ Two concurrent `task claim` calls racing on the same task return exactly one
216
+ `claimed: true`. The loser gets `claimed: false` with `currentOwner` and
217
+ `currentStatus` reflecting the winner's write.
218
+
219
+ `--owner` is required.
220
+
221
+ Response envelope:
222
+
223
+ ```text
224
+ ok: true
225
+ command: task.claim | subtask.claim
226
+ data:
227
+ claimed: true | false
228
+ currentOwner: <owner> | null
229
+ currentStatus: in_progress | todo | blocked | done
230
+ task | subtask: { ...full record... } # present only when claimed=true
231
+ ```
232
+
233
+ When `claimed` is false, `task`/`subtask` is absent. `currentOwner` tells you
234
+ who holds the lock. `currentStatus` tells you why the claim failed (already
235
+ `done`, or `in_progress` by another owner).
236
+
186
237
  ## Task done
187
238
 
188
239
  `trekoon task done <task-id>` marks a task complete and returns the next ready
@@ -289,6 +340,99 @@ trekoon --toon sync conflicts show <conflict-id>
289
340
  `list` defaults to `--mode pending`. Use `--mode all` to include resolved
290
341
  conflicts.
291
342
 
343
+ ## Migrate commands
344
+
345
+ ### `migrate status`
346
+
347
+ ```bash
348
+ trekoon --toon migrate status
349
+ ```
350
+
351
+ Reports `currentVersion`, `latestVersion`, and pending migration count.
352
+
353
+ ### `migrate rollback`
354
+
355
+ ```bash
356
+ trekoon --toon migrate rollback [--to-version <n>]
357
+ ```
358
+
359
+ Rolls back schema migrations one version (default) or down to `--to-version`.
360
+ Migrations 0004, 0005, and 0006 are irreversible (ALTER TABLE plus dependency
361
+ data cleanup). Rolling back below those versions errors with code
362
+ `migration_down_unsupported`. Take a backup first; restore by copying the
363
+ backup over `.trekoon/trekoon.db`.
364
+
365
+ ### `migrate backup`
366
+
367
+ ```bash
368
+ trekoon --toon migrate backup
369
+ trekoon --toon migrate backup --retain 5
370
+ ```
371
+
372
+ Snapshots `.trekoon/trekoon.db` to a timestamped sibling file
373
+ (`trekoon.db.backup-<ISO8601>`) using SQLite `VACUUM INTO`. The source database
374
+ is opened read-only, so a backup never mutates live state. Returns
375
+ `backupPath`, `bytes`, `migrationVersion`, and `latestVersion` for machine
376
+ consumers. Backups stay inside `.trekoon/` and are gitignored along with the
377
+ rest of the directory.
378
+
379
+ `--retain <n>` keeps the last `n` timestamped backups; older siblings are
380
+ pruned in the same call. Default is `10`. Backups created within the same
381
+ millisecond produce a deterministic collision error that names the existing
382
+ file so operators can identify it.
383
+
384
+ To restore from a backup: stop any process holding the DB, then copy the
385
+ backup file over `.trekoon/trekoon.db`.
386
+
387
+ ## Daemon (experimental)
388
+
389
+ `trekoon serve` runs Trekoon as a long-lived process listening
390
+ on a Unix-domain socket inside `<storage-root>/.trekoon/daemon.sock`. The
391
+ daemon holds the SQLite connection in memory, so subsequent invocations skip
392
+ Bun startup, module load, migration probes, and database open.
393
+
394
+ Status: **experimental**. Not on by default. The default one-shot CLI behavior
395
+ is unchanged whether or not the daemon is running.
396
+
397
+ Activate the client with one of:
398
+
399
+ ```bash
400
+ TREKOON_DAEMON=1 trekoon session
401
+ trekoon --daemon session
402
+ ```
403
+
404
+ If no daemon is reachable, the client transparently falls back to the in-process
405
+ one-shot path. Calls run against the daemon return envelopes equivalent to the
406
+ in-process call modulo:
407
+
408
+ - The per-request `requestId` and `persistedAt` fields.
409
+ - Environment variables. The client's `process.env` is **not** forwarded over
410
+ the socket; the daemon process uses the environment captured at `trekoon
411
+ serve` startup. If a command's behavior depends on an env var (e.g. an
412
+ override flag), set it before launching the daemon — not on the client side.
413
+
414
+ The daemon request contract is `{argv, cwd}` only — there is no per-call env
415
+ channel. This narrows the secret-leak surface area and keeps the equivalence
416
+ claim crisp.
417
+
418
+ Security:
419
+
420
+ - Socket file mode `0o600`; parent `.trekoon/` directory forced to `0o700`.
421
+ - The umask is tightened to `0o077` around `server.listen()` so the socket
422
+ inode is created with restrictive perms (no TOCTOU window before chmod).
423
+ - Daemon error envelopes return a sanitized message only — no stack trace,
424
+ which would otherwise leak filesystem paths or secret-bearing error text.
425
+ Stacks are still routed to the daemon's local `console.error` for operator
426
+ debugging.
427
+ - Client env is not transmitted over the socket (see equivalence note above).
428
+ - Stale sockets from prior crashes are unlinked at startup.
429
+ - On `Ctrl-C` / `SIGTERM` the socket is unlinked and the cached database
430
+ connection is closed.
431
+
432
+ Performance (see `bench/daemon-session.ts`): daemon median < 10 ms,
433
+ cold one-shot median > 50 ms — roughly a 5–10× latency reduction for
434
+ repeated calls by reusing the held-open SQLite connection.
435
+
292
436
  ## Related docs
293
437
 
294
438
  - [Quickstart](quickstart.md)
@@ -254,6 +254,12 @@ data:
254
254
  Transition details are in `data`, not `error.details`. `error` only has `code`
255
255
  and `message`.
256
256
 
257
+ **Allowed bypass:** `task done` performs an atomic single-transaction direct
258
+ write to `done` from any non-`done` status (`todo`, `blocked`, `in_progress`),
259
+ emitting one `task.updated` event — there is no intermediate `in_progress`
260
+ event when starting from `todo`/`blocked`. This is the only sanctioned
261
+ bypass of the status-machine checker.
262
+
257
263
  ## Epic progress
258
264
 
259
265
  ```bash
@@ -328,6 +334,69 @@ data:
328
334
  pendingConflicts
329
335
  ```
330
336
 
337
+ ## Task claim
338
+
339
+ ```bash
340
+ trekoon --toon task claim <task-id> --owner <owner>
341
+ trekoon --toon subtask claim <subtask-id> --owner <owner>
342
+ ```
343
+
344
+ Atomically claims a task or subtask using SQL compare-and-swap. The single
345
+ UPDATE predicate ensures exactly one concurrent caller gets `claimed: true`.
346
+
347
+ Success (claimed):
348
+
349
+ ```text
350
+ ok: true
351
+ command: task.claim | subtask.claim
352
+ data:
353
+ claimed: true
354
+ currentOwner: <owner>
355
+ currentStatus: in_progress
356
+ task | subtask: { ...full record... }
357
+ ```
358
+
359
+ Not claimed (another owner holds it, or status is done/in_progress by others):
360
+
361
+ ```text
362
+ ok: true
363
+ command: task.claim | subtask.claim
364
+ data:
365
+ claimed: false
366
+ currentOwner: <string> | null
367
+ currentStatus: in_progress | done | todo | blocked
368
+ ```
369
+
370
+ Note: `claimed: false` is a successful response (`ok: true`). The command
371
+ reports the current state, not an error condition. Check `data.claimed` to
372
+ distinguish the two cases.
373
+
374
+ Dependency gating on claim (cr-expert hardening): when the task or subtask is
375
+ in `blocked` or `todo` and has unresolved dependencies, the claim atomically
376
+ fails with `code: dependency_blocked` rather than flipping the row into
377
+ `in_progress`. This mirrors `task done` semantics so neither
378
+ forward-progress transition (`todo|blocked → in_progress` via claim,
379
+ `* → done` via `task done`) can bypass dependency resolution.
380
+
381
+ ```text
382
+ ok: false
383
+ command: task.claim | subtask.claim
384
+ error:
385
+ code: dependency_blocked
386
+ message: "task cannot transition to in_progress while dependencies are unresolved"
387
+ data:
388
+ unresolvedDependencyCount: <number>
389
+ unresolvedDependencyIds: [<id>, ...]
390
+ unresolvedDependencies: [{ id, kind, status }, ...]
391
+ ```
392
+
393
+ The only intentional direct-status-write exception in the codebase remains
394
+ `MutationService.markTaskDoneAtomically`, which bypasses
395
+ `validateStatusTransition` for the `* → done` flip but still goes through
396
+ `assertNoUnresolvedDependenciesForStatusTransition` before issuing the UPDATE.
397
+ No other call site is permitted to write `status` directly without going
398
+ through the public transition checker.
399
+
331
400
  ## Owner field in updates
332
401
 
333
402
  Task and subtask update payloads include `owner`:
@@ -538,6 +607,60 @@ error:
538
607
  message: "Pending conflicts changed before batch resolution could be applied."
539
608
  ```
540
609
 
610
+ ## Error code registry
611
+
612
+ All machine-visible error codes emitted by Trekoon. Every `error.code` value in
613
+ any `ok: false` response will be one of the following strings.
614
+
615
+ | Code | Description |
616
+ |---|---|
617
+ | `already_done` | Entity is already in `done` status; transition is a no-op. |
618
+ | `already_resolved` | Conflict was resolved by another process before this write. |
619
+ | `ambiguous_legacy_state` | Legacy worktree state is ambiguous and cannot be automatically resolved. |
620
+ | `backpressure` | SSE snapshot stream disconnected a slow client whose queued bytes exceeded the hard limit. |
621
+ | `backup_already_exists` | A backup file already exists at the target path; overwrite was not requested. |
622
+ | `backup_database_missing` | Source database file not found when attempting to create a backup. |
623
+ | `backup_failed` | Backup operation failed (I/O or copy error). |
624
+ | `cancelled` | Operation was cancelled by the user (e.g. confirmation prompt rejected). |
625
+ | `confirmation_required` | Human-mode operation requires explicit confirmation before proceeding. |
626
+ | `conflict_set_changed` | Batch conflict set changed between preview and confirmed write. |
627
+ | `daemon_start_failed` | Daemon failed to start (socket bind error or already running). |
628
+ | `database_busy` | SQLite database is locked; retry after a short wait. |
629
+ | `dependency_blocked` | Cascade update blocked because one or more descendants have unresolved dependencies. |
630
+ | `disallowed_field` | Sync resolve attempted to write a field that is not on the allow-list. |
631
+ | `events_failed` | Event log query or export failed. |
632
+ | `install_failed` | Skill installation failed (file copy or permission error). |
633
+ | `internal_error` | Unexpected internal error; inspect server logs for details. |
634
+ | `invalid_args` | Required positional arguments are missing or malformed. |
635
+ | `invalid_dependency` | Dependency edge is invalid (self-loop, wrong entity type, or duplicate). |
636
+ | `invalid_input` | One or more option values failed validation. |
637
+ | `invalid_path` | File path is invalid for the requested operation (e.g. path is a directory). |
638
+ | `invalid_source` | Source entity for a dependency or sync operation does not exist or is of wrong kind. |
639
+ | `invalid_state` | Entity or system is in a state that does not permit the requested operation. |
640
+ | `invalid_subcommand` | Unrecognised subcommand for this command group. |
641
+ | `legacy_import_failed` | Import from a legacy (pre-`.trekoon`) data directory failed. |
642
+ | `migrate_failed` | Database schema migration failed. |
643
+ | `migration_down_unsupported` | Down-migrations are not supported; only forward migrations are allowed. |
644
+ | `missing_asset` | Expected bundled asset (skill file, template) was not found. |
645
+ | `no_matching_conflicts` | `sync resolve --all` filters matched zero pending conflicts. |
646
+ | `not_found` | Requested entity (epic, task, subtask, dependency) does not exist. |
647
+ | `orphaned_external_node` | Dependency graph contains a node that belongs to a different epic. |
648
+ | `outside_repo_target` | Skill install target path is outside the repository root. |
649
+ | `permission_denied` | File-system permission denied for the requested path. |
650
+ | `precondition_failed` | `If-Match` precondition header did not match the entity's current `updatedAt`. |
651
+ | `row_not_found` | Sync resolve target row no longer exists in the database. |
652
+ | `status_transition_invalid` | Requested status transition is not permitted by the status machine. |
653
+ | `stream_unavailable` | SSE snapshot stream is not available (board not initialised or shutting down). |
654
+ | `sync_failed` | Sync pull or push operation failed. |
655
+ | `tracked_ignored_mismatch` | Worktree is tracked by Trekoon but its path is in `.gitignore`, or vice-versa. |
656
+ | `unauthorized` | Request lacks valid authentication credentials. |
657
+ | `unhandled_command` | Command matched a known group but no case handled the subcommand. |
658
+ | `unknown_command` | Top-level command token is not recognised. |
659
+ | `unknown_option` | An option flag passed to the command is not recognised. |
660
+ | `unsupported_entity_kind` | Sync resolve encountered an entity kind that the writer does not handle. |
661
+ | `update_failed` | Skill update failed (download, copy, or permission error). |
662
+ | `wrong_entity_type` | Operation requires a specific entity kind but a different kind was supplied. |
663
+
541
664
  ## Related docs
542
665
 
543
666
  - [Quickstart](quickstart.md)
@@ -69,7 +69,7 @@ if you just need to refresh the runtime assets without opening the browser.
69
69
  ## Create work
70
70
 
71
71
  ```bash
72
- trekoon epic create --title "Agent backlog stabilization" --description "Track stabilization work" --status todo
72
+ trekoon --toon epic create --title "Agent backlog stabilization" --description "Track stabilization work" --status todo
73
73
  trekoon task create --title "Implement sync status" --description "Add status reporting" --epic <epic-id> --status todo
74
74
  trekoon subtask create --task <task-id> --title "Add cursor model" --status todo
75
75
  ```
@@ -88,7 +88,7 @@ trekoon task list --all --view compact
88
88
  If you already know the full epic tree, create everything in one call:
89
89
 
90
90
  ```bash
91
- trekoon epic create \
91
+ trekoon --toon epic create \
92
92
  --title "Batch command rollout" \
93
93
  --description "Ship one-shot planning workflows" \
94
94
  --task "task-a|First task|First description|todo" \
@@ -118,7 +118,7 @@ For larger updates, use batch commands instead of looping:
118
118
  | Multiple tasks under one epic | `trekoon task create-many --epic <epic-id> --task ...` |
119
119
  | Multiple subtasks under one task | `trekoon subtask create-many <task-id> --subtask ...` |
120
120
  | Multiple dependency edges | `trekoon dep add-many --dep ...` |
121
- | Expand an existing epic | `trekoon epic expand <epic-id> ...` |
121
+ | Expand an existing epic | `trekoon --toon epic expand <epic-id> ...` |
122
122
 
123
123
  These validate the whole batch before applying, so a bad input fails the entire
124
124
  operation instead of leaving partial state.
@@ -148,6 +148,58 @@ a file extension means "write this file"; no extension means "put the default-
148
148
  named file in this directory". Use `--overwrite` to resave after the plan state
149
149
  changes.
150
150
 
151
+ ## Claim work atomically
152
+
153
+ When multiple agents or lanes work in parallel, use `claim` to avoid races:
154
+
155
+ ```bash
156
+ trekoon task claim <task-id> --owner <owner>
157
+ trekoon subtask claim <subtask-id> --owner <owner>
158
+ ```
159
+
160
+ Both commands use a SQL compare-and-swap: the claim succeeds only when the item
161
+ is `todo` or `blocked` and the owner is `NULL` or already set to `<owner>`.
162
+ The response includes `claimed` (true/false), `currentOwner`, `currentStatus`,
163
+ and the full entity record on success. Two concurrent claims return exactly one
164
+ `claimed=true`.
165
+
166
+ ## Database backup and migration
167
+
168
+ Before any manual migration recovery, snapshot the database:
169
+
170
+ ```bash
171
+ trekoon migrate backup
172
+ trekoon migrate backup --retain 5 # keep last 5 backups (default 10)
173
+ ```
174
+
175
+ This writes a timestamped copy of `.trekoon/trekoon.db` next to the live file.
176
+ To check the current schema version or roll back:
177
+
178
+ ```bash
179
+ trekoon migrate status
180
+ trekoon migrate rollback # one version back
181
+ trekoon migrate rollback --to-version 1
182
+ ```
183
+
184
+ ## Daemon mode (experimental)
185
+
186
+ > **Not for routine agent use.** `trekoon serve` and `--daemon` are
187
+ > experimental; use the default one-shot CLI path in automated workflows.
188
+
189
+ `trekoon serve` starts a foreground daemon on a Unix-domain socket inside
190
+ `.trekoon`. Subsequent calls skip Bun startup, module load, and database
191
+ open — per `bench/daemon-session.ts`: daemon median < 10 ms vs. cold
192
+ one-shot median > 50 ms:
193
+
194
+ ```bash
195
+ trekoon serve # start the daemon (foreground)
196
+ trekoon --daemon session # route a call through the daemon
197
+ TREKOON_DAEMON=1 trekoon session # same, via environment variable
198
+ ```
199
+
200
+ If the socket is missing or unreachable the client falls back silently to the
201
+ normal one-shot path. The socket is 0o600 and `.trekoon` is forced to 0o700.
202
+
151
203
  ## Check progress
152
204
 
153
205
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trekoon",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "AI-first task tracking that lives in your repo. You describe what to build, your agent plans it as a dependency graph, then executes it task by task",
5
5
  "keywords": [
6
6
  "ai",