trekoon 0.4.2 → 0.4.4

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 (40) hide show
  1. package/.agents/skills/trekoon/SKILL.md +97 -208
  2. package/.agents/skills/trekoon/reference/execution-with-team.md +87 -149
  3. package/.agents/skills/trekoon/reference/execution.md +170 -380
  4. package/.agents/skills/trekoon/reference/harness-primitives.md +77 -0
  5. package/.agents/skills/trekoon/reference/planning.md +193 -330
  6. package/.agents/skills/trekoon/reference/sync.md +56 -103
  7. package/README.md +29 -10
  8. package/docs/ai-agents.md +48 -4
  9. package/docs/commands.md +34 -25
  10. package/docs/machine-contracts.md +1 -1
  11. package/docs/quickstart.md +9 -9
  12. package/package.json +2 -2
  13. package/src/board/asset-root.ts +73 -0
  14. package/src/board/assets/app.js +5 -3
  15. package/src/board/assets/components/Component.js +6 -8
  16. package/src/board/assets/state/actions.js +3 -0
  17. package/src/board/assets/state/api.js +48 -34
  18. package/src/board/assets/state/store.js +3 -0
  19. package/src/board/event-bus.ts +15 -0
  20. package/src/board/routes.ts +94 -83
  21. package/src/board/server.ts +35 -8
  22. package/src/board/snapshot.ts +6 -0
  23. package/src/board/types.ts +2 -34
  24. package/src/board/wal-watcher.ts +170 -28
  25. package/src/commands/board.ts +20 -42
  26. package/src/commands/help.ts +11 -12
  27. package/src/commands/init.ts +0 -29
  28. package/src/commands/quickstart.ts +1 -1
  29. package/src/commands/skills.ts +17 -5
  30. package/src/domain/mutation-service.ts +61 -42
  31. package/src/domain/tracker-domain.ts +20 -16
  32. package/src/domain/types.ts +3 -0
  33. package/src/export/render-markdown.ts +1 -2
  34. package/src/runtime/daemon.ts +110 -49
  35. package/src/runtime/version.ts +10 -2
  36. package/src/storage/database.ts +9 -2
  37. package/src/storage/migrations.ts +19 -2
  38. package/src/storage/path.ts +0 -36
  39. package/src/sync/service.ts +47 -27
  40. package/src/board/install.ts +0 -196
@@ -1,129 +1,82 @@
1
1
  # Sync Reference
2
2
 
3
- ## Sync reminders
3
+ Trekoon uses one live SQLite database per repository at
4
+ `<sharedStorageRoot>/.trekoon/trekoon.db`. Linked worktrees share it. `git
5
+ checkout` and `git switch` do not roll back tracker state. Sync imports tracker
6
+ events between branches; never copy or commit the `.db` file.
4
7
 
5
- Same-branch sync is a no-op: `sync pull --from main` while on `main` produces
6
- zero conflicts and simply advances the cursor. `sync status` returns `behind=0`
7
- on the source branch. No action is needed.
8
+ Same-branch sync is a no-op. Cross-branch sync matters before merging a feature
9
+ branch back.
8
10
 
9
- Cross-branch sync matters before merging a feature branch back:
11
+ ## Before Merge
10
12
 
11
- - Before merge, pull tracker events from the base branch:
13
+ Pull tracker events from the base branch:
12
14
 
13
- ```bash
14
- trekoon --toon sync pull --from main
15
- ```
16
-
17
- - If conflicts exist, inspect and resolve them explicitly:
15
+ ```bash
16
+ trekoon --toon sync pull --from main
17
+ ```
18
18
 
19
- ```bash
20
- trekoon --toon sync conflicts list
21
- trekoon --toon sync conflicts show <conflict-id>
22
- trekoon --toon sync resolve <conflict-id> --use theirs --dry-run
23
- trekoon --toon sync resolve <conflict-id> --use ours
24
- ```
19
+ If conflicts exist:
25
20
 
26
- ### Conflict resolution: ours vs theirs
21
+ ```bash
22
+ trekoon --toon sync conflicts list
23
+ trekoon --toon sync conflicts show <conflict-id>
24
+ trekoon --toon sync resolve <conflict-id> --use theirs --dry-run
25
+ trekoon --toon sync resolve <conflict-id> --use ours
26
+ ```
27
27
 
28
- Conflicts are **field-level**, not whole-record. Each conflict targets one field
29
- (e.g., `status`, `title`, `description`) on one entity.
28
+ ## Conflict Rules
30
29
 
31
- - `--use ours` keep the current entity field value in the shared DB. The
32
- entity is not written, but the conflict record is marked resolved and a
33
- resolution event is appended.
34
- - `--use theirs` — overwrite the shared DB entity field with the source-branch
35
- value. The conflict record is marked resolved and a resolution event is
36
- appended.
37
- - `--dry-run` — preview the resolution without mutating the database. Returns
38
- `oursValue`, `theirsValue`, `wouldWrite`, and `dryRun: true`. Use this before
39
- committing to a resolution.
30
+ Conflicts are field-level, not whole-record. Each conflict targets one field on
31
+ one entity.
40
32
 
41
- **Example:** after `sync pull --from main`, a conflict appears on epic `abc123`,
42
- field `status`:
43
- - ours (current DB): `in_progress`
44
- - theirs (source branch): `done`
45
- - `--use ours` keeps status as `in_progress`
46
- - `--use theirs` changes status to `done` in the live shared DB
33
+ - `--use ours`: keep the current shared DB field value; mark conflict resolved.
34
+ - `--use theirs`: write the source-branch field value into the shared DB; mark
35
+ conflict resolved.
36
+ - `--dry-run`: preview without mutation. Returns `oursValue`, `theirsValue`,
37
+ `wouldWrite`, and `dryRun: true`.
47
38
 
48
- Always inspect conflicts with `sync conflicts show` before resolving. Choosing
49
- `theirs` without inspection can overwrite in-progress work in the shared DB.
39
+ Always inspect with `sync conflicts show` before resolving. Choosing `theirs`
40
+ without inspection can overwrite in-progress shared DB work.
50
41
 
51
- ### Understanding why conflicts happen
42
+ Typical choices:
52
43
 
53
- | Scenario | Typical resolution | Why |
44
+ | Scenario | Usually use | Why |
54
45
  |---|---|---|
55
- | Completed work vs stale main state | ours | Your branch has the latest progress |
46
+ | Completed work vs stale main | ours | Your branch has latest progress |
56
47
  | Enriched descriptions vs original | ours | Your descriptions are more detailed |
57
- | Upstream updates from another agent | theirs | Accept the newer upstream state |
58
- | User-intentional reset | theirs | Respect the user's explicit action |
48
+ | Upstream updates from another agent | theirs | Accept newer upstream state |
49
+ | User-intentional reset | theirs | Respect explicit user action |
59
50
 
60
- ### Agent decision framework
51
+ When unsure, ask the user.
61
52
 
62
- 1. List conflicts: `trekoon --toon sync conflicts list`
63
- 2. Group by pattern — are conflicts on the same field or direction?
64
- 3. If uniform pattern, batch resolve: `trekoon --toon sync resolve --all --use ours`
65
- 4. If mixed, narrow by entity or field, or inspect individually
66
- 5. When unsure, ask the user
67
-
68
- ### Batch resolve patterns
69
-
70
- Common scenarios:
53
+ ## Batch Resolve
71
54
 
72
55
  ```bash
73
- # Resolve all conflicts at once (most common after completing work)
74
- trekoon --toon sync resolve --all --use ours
75
-
76
- # Preview before resolving
77
56
  trekoon --toon sync resolve --all --use ours --dry-run
78
-
79
- # Narrow to status field conflicts only
57
+ trekoon --toon sync resolve --all --use ours
80
58
  trekoon --toon sync resolve --all --use ours --field status
81
-
82
- # Narrow to a specific entity
83
59
  trekoon --toon sync resolve --all --use theirs --entity <id>
84
-
85
- # Combine filters
86
60
  trekoon --toon sync resolve --all --use ours --entity <id> --field description
87
61
  ```
88
62
 
89
- ## Shared-database model
90
-
91
- Trekoon uses **one live SQLite database per repository**. The file lives at
92
- `<sharedStorageRoot>/.trekoon/trekoon.db`, where `sharedStorageRoot` is the
93
- parent of `git rev-parse --git-common-dir` (i.e., the main worktree root).
94
-
95
- Key consequences:
96
-
97
- - **All linked worktrees share the same database.** A status change in one
98
- worktree is immediately visible in every other worktree.
99
- - **`git checkout` / `git switch` does not change tracker state.** The database
100
- is outside the git object store, so switching branches does not roll back or
101
- swap task data.
102
- - **Sync operates on tracker events, not on the database file itself.** Use
103
- `sync pull` to import events between branches — never copy or commit the
104
- `.db` file.
105
-
106
- Treat every write as a mutation of shared repo-wide state, not branch-scoped
107
- state.
108
-
109
- **Conflicts are scoped per worktree + branch.** `sync_conflicts` rows are
110
- recorded with the originating worktree path and current branch, so resolving a
111
- conflict in one worktree never erases a peer worktree's conflict on the same
112
- entity. `sync conflicts list` and `sync resolve` from a given worktree only
113
- see and act on rows scoped to that worktree's branch.
114
-
115
- ## Worktree diagnostics and destructive scope
116
-
117
- - Inspect machine-readable storage fields when debugging worktrees:
118
- `storageMode`, `repoCommonDir`, `worktreeRoot`, `sharedStorageRoot`, and
119
- `databaseFile`.
120
- - `sharedStorageRoot` is the repo-scoped source of truth for `.trekoon` in git
121
- worktrees.
122
- - If `trekoon wipe --yes --toon` is explicitly requested, warn that it deletes
123
- shared storage for the entire repository and every linked worktree.
124
- - Wipe is destructive recovery only; it is never the right fix for a tracked DB
125
- or gitignore mistake.
126
-
127
- Trekoon stores local state in `.trekoon/trekoon.db`. In git repos and
128
- worktrees, storage resolves from the shared repository root rather than each
129
- worktree independently.
63
+ Use batch resolve only when the conflict pattern is uniform. Otherwise inspect
64
+ and resolve individually or narrow by `--entity` / `--field`.
65
+
66
+ ## Worktree Scope
67
+
68
+ Inspect machine-readable storage fields when debugging worktrees:
69
+ `storageMode`, `repoCommonDir`, `worktreeRoot`, `sharedStorageRoot`, and
70
+ `databaseFile`.
71
+
72
+ Conflicts are scoped per worktree and branch. `sync conflicts list` and
73
+ `sync resolve` only act on rows for the current worktree/branch, so resolving a
74
+ conflict does not erase a peer worktree's conflict on the same entity.
75
+
76
+ ## Destructive Recovery
77
+
78
+ `sharedStorageRoot` is the repo-scoped source of truth for `.trekoon` in git
79
+ worktrees. If the user explicitly requests `trekoon wipe --yes --toon`, warn
80
+ that it deletes shared storage for the whole repository and every linked
81
+ worktree. Wipe is destructive recovery only; it is never the fix for a tracked
82
+ DB or gitignore mistake.
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
 
@@ -182,14 +196,19 @@ call it from any non-done status.
182
196
 
183
197
  ## Local board
184
198
 
185
- Trekoon includes a browser-based board for humans who like having visual overview.
186
- No build step, no framework dependencies, works offline.
199
+ Trekoon includes a browser-based board for humans who like having a visual
200
+ overview. No build step, no framework dependencies, works offline.
187
201
 
188
202
  ```bash
189
203
  trekoon board open # starts a local server, opens browser
190
- trekoon board update # refresh assets only
191
204
  ```
192
205
 
206
+ Board code (HTML, JS, CSS, fonts) comes from the running Trekoon install.
207
+ Board data comes from the repo where `trekoon board open` is invoked. Updating
208
+ Trekoon updates the board bundle; no per-repo asset copy is needed.
209
+ Repos with an old ignored `.trekoon/board` directory keep those files on disk,
210
+ but Trekoon no longer reads or refreshes them.
211
+
193
212
  Binds to `127.0.0.1` only with a per-session token. Gives you an epics
194
213
  overview, kanban workspace per epic, task detail modals, and search. The board
195
214
  client subscribes to `/api/snapshot/stream` (SSE), so mutations from another
@@ -201,7 +220,7 @@ shell, worktree, or browser tab show up live without a manual refresh.
201
220
  | --- | --- |
202
221
  | Set up a repo | `trekoon init` |
203
222
  | Open the local board | `trekoon board open` |
204
- | Plan work | `trekoon epic create ...`, `trekoon epic expand ...` |
223
+ | Plan work | `trekoon --toon epic create ...`, `trekoon --toon epic expand ...` |
205
224
  | Create tasks in bulk | `trekoon task create-many ...` |
206
225
  | Add dependencies | `trekoon dep add-many ...` |
207
226
  | Start an agent session | `trekoon session --epic <id>` |
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
@@ -97,6 +116,17 @@ Typical flow:
97
116
 
98
117
  The core loop: **session, work, task done, repeat**.
99
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
+
100
130
  Start with a single orientation call, optionally scoped to an epic:
101
131
 
102
132
  ```bash
@@ -193,6 +223,20 @@ notes, mark it done, and repeat until there are no ready tasks or you hit a
193
223
  blocker.
194
224
  ```
195
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
+
196
240
  ### Plan and execute end to end
197
241
 
198
242
  ```text
package/docs/commands.md CHANGED
@@ -6,7 +6,7 @@ the quickest way to get started, read [Quickstart](quickstart.md) first.
6
6
  ## Command surface
7
7
 
8
8
  - `trekoon init`
9
- - `trekoon board <open|update>`
9
+ - `trekoon board <open>`
10
10
  - `trekoon help [command]`
11
11
  - `trekoon quickstart`
12
12
  - `trekoon epic <create|expand|list|show|search|replace|update|delete|progress>`
@@ -22,8 +22,8 @@ the quickest way to get started, read [Quickstart](quickstart.md) first.
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
29
  - `trekoon serve` (experimental)
@@ -50,25 +50,31 @@ also accept `-h` and `-v`.
50
50
 
51
51
  ## Board commands
52
52
 
53
- `trekoon board open` installs board assets (if needed), starts a loopback-only
54
- server on `127.0.0.1` with a random port, opens the browser, and returns the
55
- board URL plus a manual fallback URL.
53
+ `trekoon board open` starts a loopback-only server on `127.0.0.1` with a
54
+ random port, opens the browser, and returns the board URL plus a manual
55
+ fallback URL.
56
56
 
57
- `trekoon board update` refreshes board runtime assets without starting the
58
- server or opening a browser. Use this when you need to update copied assets
59
- before the next launch.
57
+ Board code (HTML, JS, CSS, fonts) comes from the running Trekoon install —
58
+ a global install serves the global package assets; a project-local install
59
+ serves the project-local package assets. Board data comes from the repo where
60
+ `trekoon board open` is invoked. Updating Trekoon updates the board bundle;
61
+ no per-repo asset copy is needed.
60
62
 
61
63
  Security model:
62
64
 
63
65
  - Every `board open` session gets a unique token
64
- - Requests must include it as `Authorization: Bearer {token}`,
65
- `x-trekoon-token` header, or `?token={token}` query parameter
66
+ - Initial board HTML bootstrap accepts `?token={token}` once, sets an
67
+ HttpOnly `trekoon_board_session` cookie, and redirects to the same URL
68
+ without the token query parameter
69
+ - Board API requests must authenticate with the session cookie,
70
+ `Authorization: Bearer {token}`, or `x-trekoon-token` header
71
+ - API routes reject token query parameters
72
+ - `/api/snapshot/stream` is authenticated by the session cookie
66
73
  - Invalid tokens return `401`
67
74
  - Static responses use `cache-control: no-store`
68
75
 
69
76
  The board is a self-hosted single-page app (vanilla JS, bundled CSS and fonts,
70
- no framework or CDN dependencies) served from `.trekoon/board`. Works fully
71
- offline once initialized.
77
+ no framework or CDN dependencies). Works fully offline.
72
78
 
73
79
  Board API endpoints (all require token authentication):
74
80
 
@@ -84,27 +90,30 @@ Board API endpoints (all require token authentication):
84
90
  | `POST` | `/api/dependencies` | Add dependency edge (sourceId, dependsOnId) |
85
91
  | `DELETE` | `/api/dependencies?sourceId=...&dependsOnId=...` | Remove dependency |
86
92
 
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
93
  Board mutations from any source — board UI, CLI in another shell, or another
93
94
  worktree — propagate to every connected client through the SSE stream. The CLI
94
95
  side is driven by a WAL-watcher that diffs the snapshot when
95
96
  `.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
-
100
- Board commands don't accept command-specific options yet. For tests and local
101
- development, `TREKOON_BOARD_ASSET_ROOT` overrides the bundled asset source.
97
+ directly. PATCH endpoints accept `If-Match: <version>` for optimistic
98
+ concurrency; RFC 7232 strong or `W/`-prefixed weak ETag forms are accepted,
99
+ but the `*` wildcard is not. A stale value returns `409` with
100
+ `currentVersion` and `providedVersion`. Missing `If-Match` is allowed for
101
+ back-compat.
102
+
103
+ Repos that already have an ignored `.trekoon/board` directory keep those files
104
+ on disk, but current Trekoon versions no longer read, create, refresh, or
105
+ delete them. Remove that directory manually only if you want to clean up the
106
+ old copied board bundle.
107
+
108
+ `trekoon board open` accepts `--reveal-token` to include the raw tokenized URL,
109
+ server token, and browser launch arguments in machine output. Other board
110
+ subcommands and flags are rejected. `TREKOON_BOARD_ASSET_ROOT` overrides the
111
+ asset source for tests and local development.
102
112
 
103
113
  ```bash
104
114
  trekoon init
105
115
  trekoon board open
106
116
  trekoon --json board open
107
- trekoon board update
108
117
  ```
109
118
 
110
119
  ## Human views
@@ -647,7 +647,7 @@ any `ok: false` response will be one of the following strings.
647
647
  | `orphaned_external_node` | Dependency graph contains a node that belongs to a different epic. |
648
648
  | `outside_repo_target` | Skill install target path is outside the repository root. |
649
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`. |
650
+ | `precondition_failed` | `If-Match` precondition header did not match the entity's current version. Error details include `currentVersion` and `providedVersion`. |
651
651
  | `row_not_found` | Sync resolve target row no longer exists in the database. |
652
652
  | `status_transition_invalid` | Requested status transition is not permitted by the status machine. |
653
653
  | `stream_unavailable` | SSE snapshot stream is not available (board not initialised or shutting down). |
@@ -50,9 +50,8 @@ trekoon --toon init
50
50
  trekoon --toon sync status
51
51
  ```
52
52
 
53
- Run `init` once per repository. It creates the shared storage root and installs
54
- the board runtime under `.trekoon/board`. If `sync status` reports
55
- `recoveryRequired` or a tracked/ignored mismatch, fix the setup before
53
+ Run `init` once per repository. It creates the shared storage root. If `sync status`
54
+ reports `recoveryRequired` or a tracked/ignored mismatch, fix the setup before
56
55
  continuing.
57
56
 
58
57
  ## Open the board
@@ -62,14 +61,15 @@ trekoon board open
62
61
  ```
63
62
 
64
63
  Starts a loopback-only server on `127.0.0.1`, opens the browser, and prints a
65
- fallback URL. The board is a self-hosted single-page app with no CDN
66
- dependencies, so it works offline once initialized. Use `trekoon board update`
67
- if you just need to refresh the runtime assets without opening the browser.
64
+ fallback URL. Board code (HTML, JS, CSS, fonts) comes from the running Trekoon
65
+ install; board data comes from the repo where the command is invoked. The board
66
+ works fully offline. To get an updated board UI, update Trekoon itself. Old
67
+ ignored `.trekoon/board` copies are left on disk but are no longer used.
68
68
 
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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trekoon",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
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",
@@ -40,7 +40,7 @@
40
40
  ],
41
41
  "scripts": {
42
42
  "run": "bun run ./src/index.ts",
43
- "build": "bun build ./src/index.ts --outdir ./dist --target bun",
43
+ "build": "bun build ./src/index.ts --outdir ./dist --target bun && cp ./package.json ./dist/package.json && rm -rf ./dist/assets && cp -R ./src/board/assets ./dist/assets",
44
44
  "test": "bun test ./tests",
45
45
  "lint": "bunx tsc --noEmit"
46
46
  },
@@ -0,0 +1,73 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ import { BoardAssetError } from "./types";
6
+
7
+ export const BOARD_BUNDLED_ASSET_DIRNAME = "assets";
8
+ export const BOARD_ENTRY_FILENAME = "index.html";
9
+ export const BOARD_ASSET_ROOT_ENV_VAR = "TREKOON_BOARD_ASSET_ROOT";
10
+
11
+ export type BoardAssetRootSource = "override" | "environment" | "package";
12
+
13
+ export interface BoardAssetRoot {
14
+ readonly assetRoot: string;
15
+ readonly entryFile: string;
16
+ readonly source: BoardAssetRootSource;
17
+ }
18
+
19
+ export interface ResolveBoardAssetRootOptions {
20
+ readonly assetRootOverride?: string;
21
+ readonly env?: NodeJS.ProcessEnv;
22
+ }
23
+
24
+ function resolvePackageBoardAssetRoot(): string {
25
+ return fileURLToPath(new URL(`./${BOARD_BUNDLED_ASSET_DIRNAME}`, import.meta.url));
26
+ }
27
+
28
+ interface SelectedAssetRoot {
29
+ readonly rootPath: string;
30
+ readonly source: BoardAssetRootSource;
31
+ }
32
+
33
+ function selectAssetRoot(options: ResolveBoardAssetRootOptions): SelectedAssetRoot {
34
+ if (options.assetRootOverride !== undefined) {
35
+ return { rootPath: resolve(options.assetRootOverride), source: "override" };
36
+ }
37
+
38
+ const env = options.env ?? process.env;
39
+ const envOverrideRaw = env[BOARD_ASSET_ROOT_ENV_VAR];
40
+ const envOverride = typeof envOverrideRaw === "string" ? envOverrideRaw.trim() : "";
41
+ if (envOverride.length > 0) {
42
+ return { rootPath: resolve(envOverride), source: "environment" };
43
+ }
44
+
45
+ return { rootPath: resolvePackageBoardAssetRoot(), source: "package" };
46
+ }
47
+
48
+ export function resolveBoardAssetRoot(options: ResolveBoardAssetRootOptions = {}): BoardAssetRoot {
49
+ const { rootPath, source } = selectAssetRoot(options);
50
+
51
+ if (!existsSync(rootPath) || !statSync(rootPath).isDirectory()) {
52
+ throw new BoardAssetError("missing_asset", `Board asset root not found at ${rootPath}`, {
53
+ assetRoot: rootPath,
54
+ source,
55
+ });
56
+ }
57
+
58
+ const entryFile = resolve(rootPath, BOARD_ENTRY_FILENAME);
59
+ if (!existsSync(entryFile)) {
60
+ throw new BoardAssetError("missing_asset", `Board entry file not found at ${entryFile}`, {
61
+ assetRoot: rootPath,
62
+ entryFile,
63
+ source,
64
+ missingFile: BOARD_ENTRY_FILENAME,
65
+ });
66
+ }
67
+
68
+ return {
69
+ assetRoot: rootPath,
70
+ entryFile,
71
+ source,
72
+ };
73
+ }
@@ -156,7 +156,7 @@ export async function bootLegacyBoard(options = {}) {
156
156
  </div>
157
157
  <span class="${sectionLabelClasses()}">Board ready</span>
158
158
  <h1 class="mt-2 text-3xl font-semibold tracking-tight text-[var(--board-text)]">No work has been published yet</h1>
159
- <p class="mx-auto mt-3 max-w-2xl text-sm leading-6 text-[var(--board-text-muted)] sm:text-base">Once the board snapshot is installed into <code class="rounded-lg border border-[var(--board-border)] bg-white/[0.04] px-2 py-1 text-[var(--board-text)]">.trekoon/board</code>, epics and tasks will appear here.</p>
159
+ <p class="mx-auto mt-3 max-w-2xl text-sm leading-6 text-[var(--board-text-muted)] sm:text-base">Create or sync an epic in this repository and it will appear here.</p>
160
160
  </div>
161
161
  </section>
162
162
  `;
@@ -479,9 +479,11 @@ export async function bootLegacyBoard(options = {}) {
479
479
  rerender,
480
480
  });
481
481
  if (typeof window !== "undefined" && typeof window.addEventListener === "function") {
482
- window.addEventListener("beforeunload", () => {
482
+ const disposeSnapshotSubscription = () => {
483
483
  snapshotSubscription.dispose();
484
- }, { once: true });
484
+ };
485
+ window.addEventListener("beforeunload", disposeSnapshotSubscription, { once: true });
486
+ window.addEventListener("pagehide", disposeSnapshotSubscription, { once: true });
485
487
  }
486
488
 
487
489
  // Actions for delegation