trekoon 0.2.1 → 0.2.5

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.
@@ -19,47 +19,67 @@ pick the right command with the fewest reads and mutations.
19
19
  - Preview replace before `--apply`.
20
20
  - Prefer `--ids` over `--all` for bulk updates.
21
21
  - Never edit `.trekoon/trekoon.db` directly.
22
+ - Treat `.trekoon` as shared repo-scoped operational state in git worktrees.
23
+ - Keep `.trekoon` gitignored; do not commit the SQLite DB as a recovery fix.
22
24
  - Never run `trekoon wipe --yes --toon` unless the user explicitly asks for it.
23
25
 
24
26
  ## Default agent loop
25
27
 
26
- Run this loop each session:
28
+ The primary loop is: **session → work → task done → repeat**.
27
29
 
28
- 1. Check sync baseline:
30
+ ### 1. Orient with a single call
29
31
 
30
- ```bash
31
- trekoon --toon sync status
32
- ```
32
+ ```bash
33
+ trekoon --toon session
34
+ ```
35
+
36
+ `session` replaces the old five-call bootstrap sequence
37
+ (init + sync status + task next + dep list + task show) with a single DB open.
38
+ It returns diagnostics, sync status, the full next-task tree with subtasks, blocker
39
+ list, and readiness counts in one envelope.
40
+
41
+ Fail fast if the envelope reports `recoveryRequired`, a storage mismatch, or any
42
+ bootstrap error. In linked worktrees, `sharedStorageRoot` may differ from
43
+ `worktreeRoot`; that is expected because the repo shares one DB across checkouts.
44
+
45
+ If the session envelope shows `behind > 0`, pull before claiming any task:
46
+
47
+ ```bash
48
+ trekoon --toon sync pull --from main
49
+ ```
50
+
51
+ This syncs tracker events (not git commits) from the source branch so task
52
+ states, dependencies, and subtrees are up to date before you start work.
33
53
 
34
- If this returns `missing_branch_db` on a fresh branch or worktree, continue
35
- with local task selection and treat sync as unavailable for now.
54
+ ### 2. Claim work explicitly
36
55
 
37
- 2. Pick the next item deterministically:
56
+ ```bash
57
+ trekoon --toon task update <task-id> --status in_progress
58
+ ```
38
59
 
39
- ```bash
40
- trekoon --toon task next
41
- trekoon --toon task ready --limit 5
42
- ```
60
+ ### 3. Finish or report a block
43
61
 
44
- 3. Inspect dependencies or downstream impact when needed:
62
+ ```bash
63
+ trekoon --toon task done <task-id>
64
+ trekoon --toon task update <task-id> --append "Blocked by <reason>" --status blocked
65
+ ```
45
66
 
46
- ```bash
47
- trekoon --toon dep list <task-id>
48
- trekoon --toon dep reverse <task-or-subtask-id>
49
- ```
67
+ `task done` replaces the old three-call transition sequence
68
+ (mark done + get next + load deps + show task) with a single call that marks the
69
+ task done and returns the next ready candidate with its full tree and blockers.
50
70
 
51
- 4. Claim work explicitly:
71
+ Append a completion note before calling `task done` when useful:
52
72
 
53
- ```bash
54
- trekoon --toon task update <task-id> --status in_progress
55
- ```
73
+ ```bash
74
+ trekoon --toon task update <task-id> --append "Completed implementation and checks"
75
+ trekoon --toon task done <task-id>
76
+ ```
56
77
 
57
- 5. Finish or report a block with appended context:
78
+ ### 4. Repeat
58
79
 
59
- ```bash
60
- trekoon --toon task update <task-id> --append "Completed implementation and checks" --status done
61
- trekoon --toon task update <task-id> --append "Blocked by <reason>" --status blocked
62
- ```
80
+ Run `session` again at the start of each new session. After `task done`, the
81
+ returned next-task envelope is sufficient to continue; a fresh `session` call is
82
+ not required mid-loop unless you need updated diagnostics or sync status.
63
83
 
64
84
  Recommended statuses for consistent workflows: `todo`, `in_progress`, `done`.
65
85
 
@@ -69,7 +89,8 @@ Use the narrowest command that answers the question.
69
89
 
70
90
  | Need | Preferred command |
71
91
  |---|---|
72
- | Next task | `trekoon --toon task next` |
92
+ | Session startup (diagnostics + sync + next task) | `trekoon --toon session` |
93
+ | Next task only | `trekoon --toon task next` |
73
94
  | A few ready options | `trekoon --toon task ready --limit 5` |
74
95
  | Direct blockers for one task | `trekoon --toon dep list <task-id>` |
75
96
  | What this item unblocks | `trekoon --toon dep reverse <task-or-subtask-id>` |
@@ -97,6 +118,28 @@ creates unless only one record is needed.
97
118
  | Multiple dependency edges across existing IDs | `trekoon --toon dep add-many --dep ...` |
98
119
  | One record only | `epic create`, `task create`, or `subtask create` |
99
120
 
121
+ ### Compact spec escaping rules
122
+
123
+ Compact specs (pipe-delimited `--task`, `--subtask`, `--dep` values) use `\` as
124
+ the escape character. Only these sequences are valid:
125
+
126
+ | Sequence | Produces |
127
+ |---|---|
128
+ | `\|` | literal `|` (not a field separator) |
129
+ | `\\` | literal `\` |
130
+ | `\n` | newline |
131
+ | `\r` | carriage return |
132
+ | `\t` | tab |
133
+
134
+ Any other `\X` combination (e.g., `\!`, `\=`, `\$`) is rejected with
135
+ `Invalid escape sequence`. To avoid accidental escapes:
136
+
137
+ - Do not use `!=` or similar operators in description text; rephrase instead
138
+ (e.g., "null does not equal sourceBranch" instead of "null !== sourceBranch").
139
+ - If a literal backslash is needed, double it: `\\`.
140
+ - When using shell line continuations (`\` at end of line), ensure the next
141
+ line's first character is not one that forms an invalid escape with `\`.
142
+
100
143
  ### Critical temp-key rule
101
144
 
102
145
  - Use plain temp keys when declaring records in compact specs, for example
@@ -229,20 +272,35 @@ Guardrails:
229
272
 
230
273
  ## Setup and fallback
231
274
 
232
- If Trekoon is unavailable or state is missing:
275
+ If Trekoon is unavailable or storage diagnostics require repair:
233
276
 
234
277
  ```bash
235
278
  trekoon --toon init
279
+ trekoon --toon sync status
236
280
  trekoon --toon quickstart
237
- trekoon --help --toon
281
+ trekoon --toon help sync
238
282
  ```
239
283
 
240
- Use `quickstart` for the canonical execution loop. Use `--help --toon` when you
241
- need exact syntax.
284
+ Rules:
285
+
286
+ - Re-bootstrap first, then re-read diagnostics.
287
+ - Stop if `recoveryRequired` stays true or diagnostics report storage mismatch.
288
+ - Do not continue with task selection after missing shared storage or broken
289
+ bootstrap.
290
+ - Do not commit `.trekoon/trekoon.db`; remove the tracked DB and keep
291
+ `.trekoon` ignored instead.
292
+
293
+ Use `quickstart` for the canonical execution loop. Use help when you need exact
294
+ syntax.
242
295
 
243
296
  ## Sync reminders
244
297
 
245
- - Run `trekoon --toon sync status` at session start and before PR or merge.
298
+ Same-branch sync is a no-op: `sync pull --from main` while on `main` produces
299
+ zero conflicts and simply advances the cursor. `sync status` returns `behind=0`
300
+ on the source branch. No action is needed.
301
+
302
+ Cross-branch sync matters before merging a feature branch back:
303
+
246
304
  - Before merge, pull tracker events from the base branch:
247
305
 
248
306
  ```bash
@@ -257,5 +315,18 @@ need exact syntax.
257
315
  trekoon --toon sync resolve <conflict-id> --use ours
258
316
  ```
259
317
 
318
+ ## Worktree diagnostics and destructive scope
319
+
320
+ - Inspect machine-readable storage fields when debugging worktrees:
321
+ `storageMode`, `repoCommonDir`, `worktreeRoot`, `sharedStorageRoot`, and
322
+ `databaseFile`.
323
+ - `sharedStorageRoot` is the repo-scoped source of truth for `.trekoon` in git
324
+ worktrees.
325
+ - If `trekoon wipe --yes --toon` is explicitly requested, warn that it deletes
326
+ shared storage for the entire repository and every linked worktree.
327
+ - Wipe is destructive recovery only; it is never the right fix for a tracked DB
328
+ or gitignore mistake.
329
+
260
330
  Trekoon stores local state in `.trekoon/trekoon.db`. In git repos and
261
- worktrees, storage resolves from the repository root.
331
+ worktrees, storage resolves from the shared repository root rather than each
332
+ worktree independently.
package/README.md CHANGED
@@ -40,7 +40,7 @@ npm i -g trekoon
40
40
 
41
41
  1. Make issue tracking fast enough for daily terminal use.
42
42
  2. Make issue data deterministic and machine-readable for AI automation.
43
- 3. Keep branch/worktree-aware state so parallel execution can be coordinated safely.
43
+ 3. Keep one repo-scoped state store that every worktree can coordinate through safely.
44
44
  4. Stay minimal in code size while preserving robustness and clear boundaries.
45
45
 
46
46
  ## Command surface
@@ -49,7 +49,8 @@ npm i -g trekoon
49
49
  - `trekoon help [command]`
50
50
  - `trekoon quickstart`
51
51
  - `trekoon epic <create|expand|list|show|search|replace|update|delete>`
52
- - `trekoon task <create|create-many|list|show|ready|next|search|replace|update|delete>`
52
+ - `trekoon session`
53
+ - `trekoon task <create|create-many|list|show|ready|next|done|search|replace|update|delete>`
53
54
  - `trekoon subtask <create|create-many|list|search|replace|update|delete>`
54
55
  - `trekoon dep <add|add-many|remove|list|reverse>`
55
56
  - `trekoon events prune [--dry-run] [--archive] [--retention-days <n>]`
@@ -117,15 +118,23 @@ trekoon epic update --ids <epic-1>,<epic-2> --status done
117
118
 
118
119
  ## Quickstart
119
120
 
120
- Trekoon is local-first: in git repos/worktrees, Trekoon resolves state to one
121
- canonical repository root (`git rev-parse --show-toplevel`) so nested
122
- invocations share the same `.trekoon/trekoon.db`.
121
+ Trekoon is local-first, but in git repos and worktrees it is **repo-shared**:
122
+ every worktree for the same repository resolves to one shared `.trekoon`
123
+ directory and one shared `.trekoon/trekoon.db`.
124
+
125
+ - `worktreeRoot` identifies the current checkout.
126
+ - `sharedStorageRoot` identifies the repository root that owns `.trekoon`.
127
+ - `databaseFile` points at the shared SQLite database.
128
+ - `.trekoon` stays gitignored on purpose because the DB is operational state,
129
+ not source code.
130
+ - Committing `.trekoon/trekoon.db` is the wrong fix for drift because it bakes
131
+ machine-local state and stale snapshots into Git.
123
132
 
124
133
  Outside git repos, Trekoon falls back to the invocation cwd.
125
134
 
126
135
  When machine output is enabled (`--json`/`--toon`) and a command resolves
127
136
  storage from a non-canonical cwd, Trekoon emits
128
- `meta.storageRootDiagnostics` to make the divergence explicit for automation.
137
+ `meta.storageRootDiagnostics` so automation can verify the storage contract.
129
138
 
130
139
  ### 1) Initialize
131
140
 
@@ -134,6 +143,15 @@ trekoon init
134
143
  trekoon --version
135
144
  ```
136
145
 
146
+ Bootstrap expectations:
147
+
148
+ - Run `trekoon --toon init` once per repository to create or re-bootstrap the
149
+ shared storage root.
150
+ - Run `trekoon --toon sync status` before agent work to inspect diagnostics.
151
+ - If diagnostics report `recoveryRequired`, a tracked/ignored mismatch, or an
152
+ ambiguous recovery path, stop and repair setup before continuing.
153
+ - Do **not** continue with task selection after broken bootstrap warnings.
154
+
137
155
  ### 2) Create epic → task → subtask
138
156
 
139
157
  ```bash
@@ -366,23 +384,52 @@ When to choose which command:
366
384
 
367
385
  ### 4) AI execution loop for agents
368
386
 
369
- Run this loop each session to pick next work deterministically:
387
+ The primary loop is: **session work task done → repeat**.
388
+
389
+ Orient with a single call that returns diagnostics, sync status, next ready
390
+ task with subtasks, blocker list, and readiness counts:
391
+
392
+ ```bash
393
+ trekoon --toon session
394
+ ```
395
+
396
+ Claim work, then finish or report a block:
370
397
 
371
398
  ```bash
372
- trekoon --toon sync status
373
- trekoon --toon task ready --limit 5
374
- trekoon --toon task next
375
- trekoon --toon dep reverse <task-or-subtask-id>
376
399
  trekoon --toon task update <task-id> --status in_progress
400
+ trekoon --toon task done <task-id>
401
+ trekoon --toon task update <task-id> --append "Blocked by <reason>" --status blocked
377
402
  ```
378
403
 
379
- When done or blocked, append context and update final status:
404
+ `task done` marks the task done and returns the next ready task with
405
+ dependencies inline, replacing the old multi-step transition.
406
+
407
+ Fail-fast rules:
408
+
409
+ - Treat `meta.storageRootDiagnostics` as the source of truth for worktree
410
+ storage.
411
+ - In linked worktrees, `sharedStorageRoot` may differ from `worktreeRoot`; that
412
+ is expected.
413
+ - If `recoveryRequired` is `true`, stop and follow the reported bootstrap or
414
+ recovery action.
415
+ - Do not fall back to a separate per-worktree DB or continue after missing
416
+ shared storage.
417
+
418
+ <details>
419
+ <summary>Legacy manual bootstrap (use <code>session</code> instead)</summary>
380
420
 
381
421
  ```bash
422
+ trekoon --toon init
423
+ trekoon --toon sync status
424
+ trekoon --toon task ready --limit 5
425
+ trekoon --toon task next
426
+ trekoon --toon dep reverse <task-or-subtask-id>
427
+ trekoon --toon task update <task-id> --status in_progress
382
428
  trekoon --toon task update <task-id> --append "Completed implementation and checks" --status done
383
- trekoon --toon task update <task-id> --append "Blocked by <reason>" --status blocked
384
429
  ```
385
430
 
431
+ </details>
432
+
386
433
  ### 5) Use TOON output for agent workflows
387
434
 
388
435
  ```bash
@@ -501,6 +548,19 @@ react deterministically:
501
548
  - `diagnostics.conflictEvents`
502
549
  - `diagnostics.errorHints`
503
550
 
551
+ Worktree diagnostics and recovery:
552
+
553
+ - Inspect `storageMode`, `repoCommonDir`, `worktreeRoot`, `sharedStorageRoot`,
554
+ and `databaseFile` in machine output when debugging worktree behavior.
555
+ - If a worktree resolves shared storage outside its checkout, that is expected
556
+ for linked worktrees and should not be “fixed” by committing `.trekoon`.
557
+ - If Git contains a tracked `.trekoon/trekoon.db`, remove it from Git history or
558
+ the index as appropriate, keep `.trekoon` ignored, and re-run
559
+ `trekoon --toon init`.
560
+ - Use `trekoon wipe --yes` only for explicit destructive recovery; it deletes
561
+ the shared storage root for the entire repository, not just the current
562
+ worktree.
563
+
504
564
  Compatibility mode for legacy sync command IDs:
505
565
 
506
566
  ```bash
@@ -590,6 +650,7 @@ Trekoon does not mutate global editor config directories.
590
650
  - [ ] done tasks/subtasks are marked completed
591
651
  - [ ] dependency graph has no stale blockers
592
652
  - [ ] final AI check: `trekoon --toon epic show <epic-id>`
653
+ - [ ] no one tried to commit `.trekoon/trekoon.db` as a worktree fix
593
654
 
594
655
  ## Machine-contract recipes (--toon)
595
656
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trekoon",
3
- "version": "0.2.1",
3
+ "version": "0.2.5",
4
4
  "description": "AI-first local issue tracker CLI.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -18,15 +18,16 @@ const ROOT_HELP = [
18
18
  "",
19
19
  "Commands:",
20
20
  " help Show root or command help",
21
- " init Initialize .trekoon storage and local DB",
22
- " quickstart Show AI execution loop + task detail workflow",
23
- " wipe Remove local Trekoon state (requires --yes)",
21
+ " init Initialize repo-shared .trekoon storage and DB",
22
+ " quickstart Show shared-storage bootstrap + AI execution loop",
23
+ " wipe Remove repo-shared Trekoon state (requires --yes)",
24
24
  " epic Epic lifecycle commands",
25
25
  " task Task lifecycle commands",
26
26
  " subtask Subtask lifecycle commands",
27
27
  " dep Dependency graph commands",
28
28
  " events Event retention and cleanup commands",
29
29
  " migrate Migration status and rollback commands",
30
+ " session One-call agent orientation (diagnostics + sync + next task)",
30
31
  " sync Cross-branch sync commands",
31
32
  " skills Project-local skill install/update/link",
32
33
  ].join("\n");
@@ -35,7 +36,9 @@ const INIT_HELP = [
35
36
  "Usage: trekoon init [--json|--toon]",
36
37
  "",
37
38
  "Purpose:",
38
- " Initialize local Trekoon storage (.trekoon) and database.",
39
+ " Initialize repo-scoped Trekoon storage (.trekoon) and database.",
40
+ " In git worktrees, every worktree shares the same repository DB.",
41
+ " Keep .trekoon gitignored; committing the SQLite DB is not a recovery path.",
39
42
  "",
40
43
  "Examples:",
41
44
  " trekoon init",
@@ -46,14 +49,16 @@ const QUICKSTART_HELP = [
46
49
  "Usage: trekoon quickstart [--json|--toon]",
47
50
  "",
48
51
  "Purpose:",
49
- " Show the canonical Trekoon AI execution loop and task-detail workflow.",
52
+ " Show shared-storage bootstrap, diagnostics, and the canonical AI loop.",
50
53
  "",
51
54
  "Flow:",
52
- " 1) trekoon --toon sync status",
53
- " 2) trekoon --toon task ready --limit 5",
54
- " 3) trekoon --toon task next",
55
- " 4) trekoon --toon dep reverse <task-or-subtask-id>",
56
- " 5) trekoon --toon task update <task-id> --status in_progress",
55
+ " 1) trekoon --toon init",
56
+ " 2) trekoon --toon sync status",
57
+ " 3) Fail fast on recoveryRequired or tracked/ignored mismatch diagnostics",
58
+ " 4) trekoon --toon task ready --limit 5",
59
+ " 5) trekoon --toon task next",
60
+ " 6) trekoon --toon dep reverse <task-or-subtask-id>",
61
+ " 7) trekoon --toon task update <task-id> --status in_progress",
57
62
  "",
58
63
  "Examples:",
59
64
  " trekoon quickstart",
@@ -64,10 +69,15 @@ const WIPE_HELP = [
64
69
  "Usage: trekoon wipe --yes [--json|--toon]",
65
70
  "",
66
71
  "Purpose:",
67
- " Remove local Trekoon state for the current repository.",
72
+ " Remove the repository's shared Trekoon storage directory.",
73
+ " In git worktrees this erases the same .trekoon state for every linked worktree.",
68
74
  "",
69
75
  "Options:",
70
- " --yes Required safety confirmation.",
76
+ " --yes Required confirmation for destructive repo-wide removal.",
77
+ "",
78
+ "Recovery guidance:",
79
+ " Use wipe only for explicit destructive recovery.",
80
+ " Do not use wipe to fix gitignore mistakes or to replace bootstrap diagnostics.",
71
81
  "",
72
82
  "Examples:",
73
83
  " trekoon wipe --yes",
@@ -312,6 +322,28 @@ const SYNC_HELP = [
312
322
  " trekoon sync resolve <conflict-id> --use ours",
313
323
  ].join("\n");
314
324
 
325
+ const SESSION_HELP = [
326
+ "Usage: trekoon session [--json|--toon]",
327
+ "",
328
+ "Purpose:",
329
+ " One-call agent orientation. Opens DB once and returns:",
330
+ " - diagnostics: storageMode, recoveryRequired, recoveryStatus",
331
+ " - sync: ahead/behind counts and pendingConflicts vs main",
332
+ " - next: full task tree with subtasks for the top ready candidate (null if none)",
333
+ " - nextDeps: blocker list with statuses for the next task (empty if none)",
334
+ " - readiness: readyCount and blockedCount across all open tasks",
335
+ "",
336
+ "Output modes:",
337
+ " human Multi-section summary (default in TTY)",
338
+ " toon Compact pipe-encoded envelope",
339
+ " json Full structured JSON envelope",
340
+ "",
341
+ "Examples:",
342
+ " trekoon session",
343
+ " trekoon --toon session",
344
+ " trekoon --json session",
345
+ ].join("\n");
346
+
315
347
  const SKILLS_HELP = [
316
348
  "Usage:",
317
349
  " trekoon skills install [--link --editor opencode|claude|pi] [--to <path>] [--allow-outside-repo]",
@@ -331,7 +363,8 @@ const SKILLS_HELP = [
331
363
  "",
332
364
  "Update behavior:",
333
365
  " - Refreshes canonical SKILL file in the install path above.",
334
- " - Reports default link states for opencode/claude/pi.",
366
+ " - Auto-creates or refreshes editor symlinks when editor config dir exists.",
367
+ " - Skips editors with no config dir or conflicting paths.",
335
368
  "",
336
369
  "Examples:",
337
370
  " trekoon skills install",
@@ -344,6 +377,7 @@ const SKILLS_HELP = [
344
377
  const COMMAND_HELP: Record<string, string> = {
345
378
  init: INIT_HELP,
346
379
  quickstart: QUICKSTART_HELP,
380
+ session: SESSION_HELP,
347
381
  wipe: WIPE_HELP,
348
382
  epic: EPIC_HELP,
349
383
  task: TASK_HELP,
@@ -1,27 +1,125 @@
1
1
  import { unexpectedFailureResult } from "./error-utils";
2
2
 
3
- import { okResult } from "../io/output";
3
+ import { DomainError } from "../domain/types";
4
+ import { failResult, okResult } from "../io/output";
4
5
  import { type CliContext, type CliResult } from "../runtime/command-types";
5
6
  import { openTrekoonDatabase, type TrekoonDatabase } from "../storage/database";
6
7
 
8
+ function buildRecoverySummary(database: TrekoonDatabase): string[] {
9
+ const diagnostics = database.diagnostics;
10
+ const lines: string[] = [];
11
+
12
+ if (diagnostics.recoveryStatus === "no_legacy_state") {
13
+ lines.push("Recovery status: no legacy worktree-local state detected.");
14
+ return lines;
15
+ }
16
+
17
+ if (diagnostics.recoveryStatus === "safe_auto_migrate") {
18
+ if (diagnostics.autoMigratedLegacyState) {
19
+ lines.push("Recovery status: safe auto-migrate completed.");
20
+ lines.push(`Imported from: ${diagnostics.importedFromLegacyDatabase}`);
21
+ lines.push(`Backups created: ${diagnostics.backupFiles.join(", ")}`);
22
+ } else {
23
+ lines.push("Recovery status: legacy worktree-local state detected.");
24
+ lines.push("Shared storage already exists; no import was required.");
25
+ }
26
+
27
+ lines.push(`Operator action: ${diagnostics.operatorAction}`);
28
+ return lines;
29
+ }
30
+
31
+ lines.push(`Recovery status: ${diagnostics.recoveryStatus}`);
32
+ lines.push(`Operator action: ${diagnostics.operatorAction}`);
33
+ return lines;
34
+ }
35
+
36
+ function recoveryFailureResult(error: DomainError): CliResult | null {
37
+ if (error.code !== "ambiguous_legacy_state" && error.code !== "tracked_ignored_mismatch") {
38
+ return null;
39
+ }
40
+
41
+ const details = error.details ?? {};
42
+ const status = typeof details.status === "string" ? details.status : error.code;
43
+ const operatorAction = typeof details.operatorAction === "string" ? details.operatorAction : error.message;
44
+ const legacyDatabaseFiles = Array.isArray(details.legacyDatabaseFiles) ? details.legacyDatabaseFiles : [];
45
+ const trackedStorageFiles = Array.isArray(details.trackedStorageFiles) ? details.trackedStorageFiles : [];
46
+ const humanLines: string[] = [
47
+ "Trekoon init requires operator action.",
48
+ `Recovery status: ${status}`,
49
+ error.message,
50
+ `Operator action: ${operatorAction}`,
51
+ ];
52
+
53
+ if (legacyDatabaseFiles.length > 0) {
54
+ humanLines.push(`Legacy databases: ${legacyDatabaseFiles.join(", ")}`);
55
+ }
56
+
57
+ if (trackedStorageFiles.length > 0) {
58
+ humanLines.push(`Tracked storage files: ${trackedStorageFiles.join(", ")}`);
59
+ }
60
+
61
+ return failResult({
62
+ command: "init",
63
+ human: humanLines.join("\n"),
64
+ data: {
65
+ status,
66
+ legacyDatabaseFiles,
67
+ trackedStorageFiles,
68
+ operatorAction,
69
+ },
70
+ error: {
71
+ code: error.code,
72
+ message: error.message,
73
+ },
74
+ });
75
+ }
76
+
7
77
  export async function runInit(context: CliContext): Promise<CliResult> {
8
78
  let database: TrekoonDatabase | undefined;
9
79
 
10
80
  try {
11
81
  database = openTrekoonDatabase(context.cwd);
82
+ const diagnostics = database.diagnostics;
83
+ const humanLines: string[] = [
84
+ "Trekoon initialized.",
85
+ `Storage mode: ${diagnostics.storageMode}`,
86
+ `Worktree root: ${diagnostics.worktreeRoot}`,
87
+ `Shared storage root: ${diagnostics.sharedStorageRoot}`,
88
+ `Storage directory: ${database.paths.storageDir}`,
89
+ `Database file: ${database.paths.databaseFile}`,
90
+ ...buildRecoverySummary(database),
91
+ ];
92
+
12
93
  return okResult({
13
94
  command: "init",
14
- human: [
15
- "Trekoon initialized.",
16
- `Storage directory: ${database.paths.storageDir}`,
17
- `Database file: ${database.paths.databaseFile}`,
18
- ].join("\n"),
95
+ human: humanLines.join("\n"),
19
96
  data: {
97
+ invocationCwd: diagnostics.invocationCwd,
98
+ storageMode: diagnostics.storageMode,
99
+ repoCommonDir: diagnostics.repoCommonDir,
100
+ worktreeRoot: diagnostics.worktreeRoot,
101
+ sharedStorageRoot: diagnostics.sharedStorageRoot,
20
102
  storageDir: database.paths.storageDir,
21
103
  databaseFile: database.paths.databaseFile,
104
+ legacyStateDetected: diagnostics.legacyStateDetected,
105
+ recoveryRequired: diagnostics.recoveryRequired,
106
+ recoveryStatus: diagnostics.recoveryStatus,
107
+ legacyDatabaseFiles: diagnostics.legacyDatabaseFiles,
108
+ backupFiles: diagnostics.backupFiles,
109
+ trackedStorageFiles: diagnostics.trackedStorageFiles,
110
+ autoMigratedLegacyState: diagnostics.autoMigratedLegacyState,
111
+ importedFromLegacyDatabase: diagnostics.importedFromLegacyDatabase,
112
+ operatorAction: diagnostics.operatorAction,
22
113
  },
23
114
  });
24
115
  } catch (error: unknown) {
116
+ if (error instanceof DomainError) {
117
+ const recoveryFailure = recoveryFailureResult(error);
118
+ if (recoveryFailure !== null) {
119
+ return recoveryFailure;
120
+ }
121
+ }
122
+
25
123
  return unexpectedFailureResult(error, {
26
124
  command: "init",
27
125
  human: "Unexpected init command failure",