@jamesaphoenix/tx-cli 0.4.3 → 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 (96) hide show
  1. package/dist/cli.js +1 -6
  2. package/dist/commands/attempt.d.ts +1 -1
  3. package/dist/commands/attempt.js +5 -4
  4. package/dist/commands/bulk.js +8 -7
  5. package/dist/commands/claim.js +4 -3
  6. package/dist/commands/cycle.js +2 -1
  7. package/dist/commands/dep.d.ts +1 -1
  8. package/dist/commands/dep.js +3 -2
  9. package/dist/commands/doc.d.ts +1 -1
  10. package/dist/commands/doc.js +13 -12
  11. package/dist/commands/doctor.d.ts +1 -1
  12. package/dist/commands/hierarchy.js +3 -2
  13. package/dist/commands/invariant.d.ts +1 -1
  14. package/dist/commands/invariant.js +2 -1
  15. package/dist/commands/learning.d.ts +3 -3
  16. package/dist/commands/sync-platform.js +4 -3
  17. package/dist/commands/sync.d.ts +1 -1
  18. package/dist/commands/sync.js +3 -2
  19. package/dist/commands/task.d.ts +4 -4
  20. package/dist/commands/task.js +8 -7
  21. package/dist/commands/trace.js +14 -13
  22. package/dist/commands/validate.js +2 -1
  23. package/package.json +10 -3
  24. package/dist/cli-exit.d.ts.map +0 -1
  25. package/dist/cli-exit.js.map +0 -1
  26. package/dist/cli.d.ts.map +0 -1
  27. package/dist/cli.js.map +0 -1
  28. package/dist/commands/attempt.d.ts.map +0 -1
  29. package/dist/commands/attempt.js.map +0 -1
  30. package/dist/commands/bulk.d.ts.map +0 -1
  31. package/dist/commands/bulk.js.map +0 -1
  32. package/dist/commands/claim.d.ts.map +0 -1
  33. package/dist/commands/claim.js.map +0 -1
  34. package/dist/commands/compact.d.ts.map +0 -1
  35. package/dist/commands/compact.js.map +0 -1
  36. package/dist/commands/coordinator.d.ts.map +0 -1
  37. package/dist/commands/coordinator.js.map +0 -1
  38. package/dist/commands/cycle.d.ts.map +0 -1
  39. package/dist/commands/cycle.js.map +0 -1
  40. package/dist/commands/daemon.d.ts.map +0 -1
  41. package/dist/commands/daemon.js.map +0 -1
  42. package/dist/commands/dashboard.d.ts.map +0 -1
  43. package/dist/commands/dashboard.js.map +0 -1
  44. package/dist/commands/dashboard.test.d.ts +0 -2
  45. package/dist/commands/dashboard.test.d.ts.map +0 -1
  46. package/dist/commands/dashboard.test.js +0 -99
  47. package/dist/commands/dashboard.test.js.map +0 -1
  48. package/dist/commands/dep.d.ts.map +0 -1
  49. package/dist/commands/dep.js.map +0 -1
  50. package/dist/commands/doc.d.ts.map +0 -1
  51. package/dist/commands/doc.js.map +0 -1
  52. package/dist/commands/doctor.d.ts.map +0 -1
  53. package/dist/commands/doctor.js.map +0 -1
  54. package/dist/commands/graph.d.ts.map +0 -1
  55. package/dist/commands/graph.js.map +0 -1
  56. package/dist/commands/hierarchy.d.ts.map +0 -1
  57. package/dist/commands/hierarchy.js.map +0 -1
  58. package/dist/commands/hooks.d.ts.map +0 -1
  59. package/dist/commands/hooks.js.map +0 -1
  60. package/dist/commands/invariant.d.ts.map +0 -1
  61. package/dist/commands/invariant.js.map +0 -1
  62. package/dist/commands/learning.d.ts.map +0 -1
  63. package/dist/commands/learning.js.map +0 -1
  64. package/dist/commands/migrate.d.ts.map +0 -1
  65. package/dist/commands/migrate.js.map +0 -1
  66. package/dist/commands/orchestrator.d.ts.map +0 -1
  67. package/dist/commands/orchestrator.js.map +0 -1
  68. package/dist/commands/stats.d.ts.map +0 -1
  69. package/dist/commands/stats.js.map +0 -1
  70. package/dist/commands/sync-platform.d.ts.map +0 -1
  71. package/dist/commands/sync-platform.js.map +0 -1
  72. package/dist/commands/sync.d.ts.map +0 -1
  73. package/dist/commands/sync.js.map +0 -1
  74. package/dist/commands/task.d.ts.map +0 -1
  75. package/dist/commands/task.js.map +0 -1
  76. package/dist/commands/test.d.ts.map +0 -1
  77. package/dist/commands/test.js.map +0 -1
  78. package/dist/commands/trace.d.ts.map +0 -1
  79. package/dist/commands/trace.js.map +0 -1
  80. package/dist/commands/validate.d.ts.map +0 -1
  81. package/dist/commands/validate.js.map +0 -1
  82. package/dist/commands/worker.d.ts.map +0 -1
  83. package/dist/commands/worker.js.map +0 -1
  84. package/dist/help.d.ts.map +0 -1
  85. package/dist/help.js.map +0 -1
  86. package/dist/output.d.ts.map +0 -1
  87. package/dist/output.js.map +0 -1
  88. package/dist/tx +0 -0
  89. package/dist/utils/parse.d.ts.map +0 -1
  90. package/dist/utils/parse.js.map +0 -1
  91. package/dist/utils/parse.test.d.ts +0 -2
  92. package/dist/utils/parse.test.d.ts.map +0 -1
  93. package/dist/utils/parse.test.js +0 -140
  94. package/dist/utils/parse.test.js.map +0 -1
  95. package/dist/version.d.ts.map +0 -1
  96. package/dist/version.js.map +0 -1
package/dist/cli.js CHANGED
@@ -291,6 +291,7 @@ const errorExitCodes = {
291
291
  ClaimNotFoundError: 2,
292
292
  DocNotFoundError: 2,
293
293
  InvariantNotFoundError: 2,
294
+ HasChildrenError: 1,
294
295
  ValidationError: 1,
295
296
  CircularDependencyError: 1,
296
297
  DatabaseError: 1,
@@ -315,12 +316,6 @@ Effect.catchAll((error) => {
315
316
  _exitCode = errorExitCodes[tag] ?? 1;
316
317
  return Effect.void;
317
318
  }
318
- if (tag === "HasChildrenError") {
319
- console.error(err.message ?? `Cannot delete task with children`);
320
- console.error("Hint: use --cascade to delete with all children, or delete/move children first.");
321
- _exitCode = 1;
322
- return Effect.void;
323
- }
324
319
  console.error(`Error: ${err.message ?? String(error)}`);
325
320
  _exitCode = 1;
326
321
  return Effect.void;
@@ -4,6 +4,6 @@
4
4
  import { Effect } from "effect";
5
5
  import { AttemptService, TaskService } from "@jamesaphoenix/tx-core";
6
6
  import { type Flags } from "../utils/parse.js";
7
- export declare const tryAttempt: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError, AttemptService>;
7
+ export declare const tryAttempt: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").TaskNotFoundError, AttemptService>;
8
8
  export declare const attempts: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError, TaskService | AttemptService>;
9
9
  //# sourceMappingURL=attempt.d.ts.map
@@ -5,12 +5,13 @@ import { Effect } from "effect";
5
5
  import { AttemptService, TaskService } from "@jamesaphoenix/tx-core";
6
6
  import { toJson } from "../output.js";
7
7
  import { flag, parseTaskId } from "../utils/parse.js";
8
+ import { CliExitError } from "../cli-exit.js";
8
9
  export const tryAttempt = (pos, flags) => Effect.gen(function* () {
9
10
  const rawTaskId = pos[0];
10
11
  const approach = pos[1];
11
12
  if (!rawTaskId || !approach) {
12
13
  console.error("Usage: tx try <task-id> <approach> --failed|--succeeded [reason]");
13
- process.exit(1);
14
+ throw new CliExitError(1);
14
15
  }
15
16
  const taskId = parseTaskId(rawTaskId);
16
17
  // Check for --failed and --succeeded flags
@@ -23,11 +24,11 @@ export const tryAttempt = (pos, flags) => Effect.gen(function* () {
23
24
  // Validate mutually exclusive flags
24
25
  if (hasFailedFlag && hasSucceededFlag) {
25
26
  console.error("Error: --failed and --succeeded are mutually exclusive");
26
- process.exit(1);
27
+ throw new CliExitError(1);
27
28
  }
28
29
  if (!hasFailedFlag && !hasSucceededFlag) {
29
30
  console.error("Error: Must specify either --failed or --succeeded");
30
- process.exit(1);
31
+ throw new CliExitError(1);
31
32
  }
32
33
  const outcome = hasFailedFlag ? "failed" : "succeeded";
33
34
  // Reason can be the value of the flag (if string) or positional arg
@@ -61,7 +62,7 @@ export const attempts = (pos, flags) => Effect.gen(function* () {
61
62
  const rawTaskId = pos[0];
62
63
  if (!rawTaskId) {
63
64
  console.error("Usage: tx attempts <task-id> [--json]");
64
- process.exit(1);
65
+ throw new CliExitError(1);
65
66
  }
66
67
  const taskId = parseTaskId(rawTaskId);
67
68
  const attemptSvc = yield* AttemptService;
@@ -5,6 +5,7 @@ import { Effect } from "effect";
5
5
  import { TaskService, ReadyService } from "@jamesaphoenix/tx-core";
6
6
  import { flag, parseTaskId } from "../utils/parse.js";
7
7
  import { toJson } from "../output.js";
8
+ import { CliExitError } from "../cli-exit.js";
8
9
  /** Extract error message safely without unsafe 'as' casts. */
9
10
  function extractErrorMessage(error) {
10
11
  if (error instanceof Error)
@@ -30,7 +31,7 @@ export const bulk = (pos, flags) => Effect.gen(function* () {
30
31
  if (!subcommand) {
31
32
  console.error("Usage: tx bulk <done|score|reset|delete> <id...> [options]");
32
33
  console.error("Run 'tx bulk --help' for more information");
33
- process.exit(1);
34
+ throw new CliExitError(1);
34
35
  }
35
36
  switch (subcommand) {
36
37
  case "done":
@@ -44,13 +45,13 @@ export const bulk = (pos, flags) => Effect.gen(function* () {
44
45
  default:
45
46
  console.error(`Unknown bulk subcommand: ${subcommand}`);
46
47
  console.error("Valid subcommands: done, score, reset, delete");
47
- process.exit(1);
48
+ throw new CliExitError(1);
48
49
  }
49
50
  });
50
51
  const bulkDone = (pos, flags) => Effect.gen(function* () {
51
52
  if (pos.length === 0) {
52
53
  console.error("Usage: tx bulk done <id> [id...] [--json]");
53
- process.exit(1);
54
+ throw new CliExitError(1);
54
55
  }
55
56
  const taskSvc = yield* TaskService;
56
57
  const readySvc = yield* ReadyService;
@@ -90,12 +91,12 @@ const bulkDone = (pos, flags) => Effect.gen(function* () {
90
91
  const bulkScore = (pos, flags) => Effect.gen(function* () {
91
92
  if (pos.length < 2) {
92
93
  console.error("Usage: tx bulk score <score> <id> [id...] [--json]");
93
- process.exit(1);
94
+ throw new CliExitError(1);
94
95
  }
95
96
  const scoreVal = parseInt(pos[0], 10);
96
97
  if (Number.isNaN(scoreVal)) {
97
98
  console.error(`Invalid score: "${pos[0]}" is not a valid number`);
98
- process.exit(1);
99
+ throw new CliExitError(1);
99
100
  }
100
101
  const ids = pos.slice(1);
101
102
  const taskSvc = yield* TaskService;
@@ -120,7 +121,7 @@ const bulkScore = (pos, flags) => Effect.gen(function* () {
120
121
  const bulkReset = (pos, flags) => Effect.gen(function* () {
121
122
  if (pos.length === 0) {
122
123
  console.error("Usage: tx bulk reset <id> [id...] [--json]");
123
- process.exit(1);
124
+ throw new CliExitError(1);
124
125
  }
125
126
  const taskSvc = yield* TaskService;
126
127
  const result = { succeeded: [], failed: [] };
@@ -144,7 +145,7 @@ const bulkReset = (pos, flags) => Effect.gen(function* () {
144
145
  const bulkDelete = (pos, flags) => Effect.gen(function* () {
145
146
  if (pos.length === 0) {
146
147
  console.error("Usage: tx bulk delete <id> [id...] [--json]");
147
- process.exit(1);
148
+ throw new CliExitError(1);
148
149
  }
149
150
  const taskSvc = yield* TaskService;
150
151
  const result = { succeeded: [], failed: [] };
@@ -9,6 +9,7 @@ import { Effect } from "effect";
9
9
  import { ClaimService } from "@jamesaphoenix/tx-core";
10
10
  import { toJson } from "../output.js";
11
11
  import { flag, parseIntOpt, parseTaskId } from "../utils/parse.js";
12
+ import { CliExitError } from "../cli-exit.js";
12
13
  /**
13
14
  * Claim a task for a worker with a lease.
14
15
  *
@@ -27,7 +28,7 @@ export const claim = (pos, flags) => Effect.gen(function* () {
27
28
  console.error("Options:");
28
29
  console.error(" --lease <m> Lease duration in minutes (default: 30)");
29
30
  console.error(" --json Output in JSON format");
30
- process.exit(1);
31
+ throw new CliExitError(1);
31
32
  }
32
33
  const taskId = parseTaskId(rawTaskId);
33
34
  const leaseMinutes = parseIntOpt(flags, "lease", "lease");
@@ -54,7 +55,7 @@ export const claimRelease = (pos, flags) => Effect.gen(function* () {
54
55
  const workerId = pos[1];
55
56
  if (!rawTaskId || !workerId) {
56
57
  console.error("Usage: tx claim:release <task-id> <worker-id> [--json]");
57
- process.exit(1);
58
+ throw new CliExitError(1);
58
59
  }
59
60
  const taskId = parseTaskId(rawTaskId);
60
61
  const svc = yield* ClaimService;
@@ -79,7 +80,7 @@ export const claimRenew = (pos, flags) => Effect.gen(function* () {
79
80
  const workerId = pos[1];
80
81
  if (!rawTaskId || !workerId) {
81
82
  console.error("Usage: tx claim:renew <task-id> <worker-id> [--json]");
82
- process.exit(1);
83
+ throw new CliExitError(1);
83
84
  }
84
85
  const taskId = parseTaskId(rawTaskId);
85
86
  const svc = yield* ClaimService;
@@ -8,6 +8,7 @@ import { Effect } from "effect";
8
8
  import { CycleScanService } from "@jamesaphoenix/tx-core";
9
9
  import { toJson } from "../output.js";
10
10
  import { flag, opt, parseIntOpt } from "../utils/parse.js";
11
+ import { CliExitError } from "../cli-exit.js";
11
12
  /** Dispatch cycle command. */
12
13
  export const cycle = (_pos, flags) => {
13
14
  const taskPrompt = opt(flags, "task-prompt");
@@ -32,7 +33,7 @@ export const cycle = (_pos, flags) => {
32
33
  console.error(" --dry-run Report only, no DB writes");
33
34
  console.error(" --score <N> Base score for new tasks (default: 500)");
34
35
  console.error(" --json Output as JSON");
35
- process.exit(1);
36
+ throw new CliExitError(1);
36
37
  });
37
38
  }
38
39
  return Effect.gen(function* () {
@@ -4,6 +4,6 @@
4
4
  import { Effect } from "effect";
5
5
  import { TaskService, DependencyService } from "@jamesaphoenix/tx-core";
6
6
  import { type Flags } from "../utils/parse.js";
7
- export declare const block: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").CircularDependencyError, TaskService | DependencyService>;
7
+ export declare const block: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").CircularDependencyError, TaskService | DependencyService>;
8
8
  export declare const unblock: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").DependencyNotFoundError, TaskService | DependencyService>;
9
9
  //# sourceMappingURL=dep.d.ts.map
@@ -5,12 +5,13 @@ import { Effect } from "effect";
5
5
  import { TaskService, DependencyService } from "@jamesaphoenix/tx-core";
6
6
  import { toJson } from "../output.js";
7
7
  import { flag, parseTaskId } from "../utils/parse.js";
8
+ import { CliExitError } from "../cli-exit.js";
8
9
  export const block = (pos, flags) => Effect.gen(function* () {
9
10
  const rawId = pos[0];
10
11
  const rawBlocker = pos[1];
11
12
  if (!rawId || !rawBlocker) {
12
13
  console.error("Usage: tx block <task-id> <blocker-id> [--json]");
13
- process.exit(1);
14
+ throw new CliExitError(1);
14
15
  }
15
16
  const id = parseTaskId(rawId);
16
17
  const blocker = parseTaskId(rawBlocker);
@@ -31,7 +32,7 @@ export const unblock = (pos, flags) => Effect.gen(function* () {
31
32
  const rawBlocker = pos[1];
32
33
  if (!rawId || !rawBlocker) {
33
34
  console.error("Usage: tx unblock <task-id> <blocker-id> [--json]");
34
- process.exit(1);
35
+ throw new CliExitError(1);
35
36
  }
36
37
  const id = parseTaskId(rawId);
37
38
  const blocker = parseTaskId(rawBlocker);
@@ -6,5 +6,5 @@ import { Effect } from "effect";
6
6
  import { DocService } from "@jamesaphoenix/tx-core";
7
7
  import { type Flags } from "../utils/parse.js";
8
8
  /** Dispatch doc subcommands. */
9
- export declare const doc: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").InvalidDocYamlError | import("@jamesaphoenix/tx-core").DocNotFoundError, DocService>;
9
+ export declare const doc: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").DocNotFoundError | import("@jamesaphoenix/tx-core").InvalidDocYamlError | import("@jamesaphoenix/tx-core").ValidationError, DocService>;
10
10
  //# sourceMappingURL=doc.d.ts.map
@@ -9,6 +9,7 @@ import { DocService } from "@jamesaphoenix/tx-core";
9
9
  import { DOC_KINDS } from "@jamesaphoenix/tx-types";
10
10
  import { toJson } from "../output.js";
11
11
  import { flag, opt } from "../utils/parse.js";
12
+ import { CliExitError } from "../cli-exit.js";
12
13
  const docKindStrings = DOC_KINDS;
13
14
  /** Dispatch doc subcommands. */
14
15
  export const doc = (pos, flags) => {
@@ -31,7 +32,7 @@ export const doc = (pos, flags) => {
31
32
  return Effect.sync(() => {
32
33
  console.error(`Unknown doc subcommand: ${sub ?? "(none)"}`);
33
34
  console.error("Run 'tx doc --help' for usage information");
34
- process.exit(1);
35
+ throw new CliExitError(1);
35
36
  });
36
37
  }
37
38
  };
@@ -41,11 +42,11 @@ const docAdd = (pos, flags) => Effect.gen(function* () {
41
42
  if (!kind || !name) {
42
43
  console.error("Usage: tx doc add <kind> <name> [--title <title>]");
43
44
  console.error(" Kinds: overview, prd, design");
44
- process.exit(1);
45
+ throw new CliExitError(1);
45
46
  }
46
47
  if (!docKindStrings.includes(kind)) {
47
48
  console.error(`Invalid kind: ${kind}. Must be one of: ${DOC_KINDS.join(", ")}`);
48
- process.exit(1);
49
+ throw new CliExitError(1);
49
50
  }
50
51
  const title = opt(flags, "title", "t") ?? name;
51
52
  // Generate template YAML
@@ -70,7 +71,7 @@ const docEdit = (pos, _flags) => Effect.gen(function* () {
70
71
  const name = pos[0];
71
72
  if (!name) {
72
73
  console.error("Usage: tx doc edit <name>");
73
- process.exit(1);
74
+ throw new CliExitError(1);
74
75
  }
75
76
  const svc = yield* DocService;
76
77
  const doc = yield* svc.get(name);
@@ -81,14 +82,14 @@ const docEdit = (pos, _flags) => Effect.gen(function* () {
81
82
  }
82
83
  catch {
83
84
  console.error(`Failed to open editor: ${editor}`);
84
- process.exit(1);
85
+ throw new CliExitError(1);
85
86
  }
86
87
  });
87
88
  const docShow = (pos, flags) => Effect.gen(function* () {
88
89
  const name = pos[0];
89
90
  if (!name) {
90
91
  console.error("Usage: tx doc show <name> [--md] [--json]");
91
- process.exit(1);
92
+ throw new CliExitError(1);
92
93
  }
93
94
  const svc = yield* DocService;
94
95
  const doc = yield* svc.get(name);
@@ -162,7 +163,7 @@ const docLock = (pos, flags) => Effect.gen(function* () {
162
163
  const name = pos[0];
163
164
  if (!name) {
164
165
  console.error("Usage: tx doc lock <name>");
165
- process.exit(1);
166
+ throw new CliExitError(1);
166
167
  }
167
168
  const svc = yield* DocService;
168
169
  const doc = yield* svc.lock(name);
@@ -182,7 +183,7 @@ const docVersion = (pos, flags) => Effect.gen(function* () {
182
183
  const name = pos[0];
183
184
  if (!name) {
184
185
  console.error("Usage: tx doc version <name>");
185
- process.exit(1);
186
+ throw new CliExitError(1);
186
187
  }
187
188
  const svc = yield* DocService;
188
189
  const doc = yield* svc.createVersion(name);
@@ -200,7 +201,7 @@ const docLink = (pos, flags) => Effect.gen(function* () {
200
201
  const to = pos[1];
201
202
  if (!from || !to) {
202
203
  console.error("Usage: tx doc link <from-name> <to-name> [--type <link-type>]");
203
- process.exit(1);
204
+ throw new CliExitError(1);
204
205
  }
205
206
  const linkType = opt(flags, "type");
206
207
  const svc = yield* DocService;
@@ -217,7 +218,7 @@ const docAttach = (pos, flags) => Effect.gen(function* () {
217
218
  const docName = pos[1];
218
219
  if (!taskId || !docName) {
219
220
  console.error("Usage: tx doc attach <task-id> <doc-name> [--type implements|references]");
220
- process.exit(1);
221
+ throw new CliExitError(1);
221
222
  }
222
223
  const linkType = (opt(flags, "type") ?? "implements");
223
224
  const svc = yield* DocService;
@@ -234,7 +235,7 @@ const docPatch = (pos, flags) => Effect.gen(function* () {
234
235
  const patchName = pos[1];
235
236
  if (!designName || !patchName) {
236
237
  console.error("Usage: tx doc patch <design-name> <patch-name> [--title <title>]");
237
- process.exit(1);
238
+ throw new CliExitError(1);
238
239
  }
239
240
  const title = opt(flags, "title", "t") ?? patchName;
240
241
  const svc = yield* DocService;
@@ -270,7 +271,7 @@ const docDrift = (pos, flags) => Effect.gen(function* () {
270
271
  const name = pos[0];
271
272
  if (!name) {
272
273
  console.error("Usage: tx doc drift <name>");
273
- process.exit(1);
274
+ throw new CliExitError(1);
274
275
  }
275
276
  const svc = yield* DocService;
276
277
  const warnings = yield* svc.detectDrift(name);
@@ -4,6 +4,6 @@
4
4
  import { Effect } from "effect";
5
5
  import { SqliteClient, MigrationService } from "@jamesaphoenix/tx-core";
6
6
  type Flags = Record<string, string | boolean>;
7
- export declare const doctor: (_pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError, MigrationService | SqliteClient>;
7
+ export declare const doctor: (_pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError, SqliteClient | MigrationService>;
8
8
  export {};
9
9
  //# sourceMappingURL=doctor.d.ts.map
@@ -5,11 +5,12 @@ import { Effect } from "effect";
5
5
  import { TaskService } from "@jamesaphoenix/tx-core";
6
6
  import { toJson, formatTaskLine } from "../output.js";
7
7
  import { flag, parseTaskId } from "../utils/parse.js";
8
+ import { CliExitError } from "../cli-exit.js";
8
9
  export const children = (pos, flags) => Effect.gen(function* () {
9
10
  const raw = pos[0];
10
11
  if (!raw) {
11
12
  console.error("Usage: tx children <id> [--json]");
12
- process.exit(1);
13
+ throw new CliExitError(1);
13
14
  }
14
15
  const id = parseTaskId(raw);
15
16
  const svc = yield* TaskService;
@@ -34,7 +35,7 @@ export const tree = (pos, flags) => Effect.gen(function* () {
34
35
  const raw = pos[0];
35
36
  if (!raw) {
36
37
  console.error("Usage: tx tree <id> [--json]");
37
- process.exit(1);
38
+ throw new CliExitError(1);
38
39
  }
39
40
  const id = parseTaskId(raw);
40
41
  const svc = yield* TaskService;
@@ -5,5 +5,5 @@ import { Effect } from "effect";
5
5
  import { DocService } from "@jamesaphoenix/tx-core";
6
6
  import { type Flags } from "../utils/parse.js";
7
7
  /** Dispatch invariant subcommands. */
8
- export declare const invariant: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").InvalidDocYamlError | import("@jamesaphoenix/tx-core").DocNotFoundError, DocService> | Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").InvariantNotFoundError, DocService>;
8
+ export declare const invariant: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").InvariantNotFoundError, DocService> | Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").DocNotFoundError | import("@jamesaphoenix/tx-core").InvalidDocYamlError, DocService>;
9
9
  //# sourceMappingURL=invariant.d.ts.map
@@ -5,6 +5,7 @@ import { Effect } from "effect";
5
5
  import { DocService } from "@jamesaphoenix/tx-core";
6
6
  import { toJson } from "../output.js";
7
7
  import { flag, opt } from "../utils/parse.js";
8
+ import { CliExitError } from "../cli-exit.js";
8
9
  /** Dispatch invariant subcommands. */
9
10
  export const invariant = (pos, flags) => {
10
11
  const sub = pos[0];
@@ -18,7 +19,7 @@ export const invariant = (pos, flags) => {
18
19
  return Effect.sync(() => {
19
20
  console.error(`Unknown invariant subcommand: ${sub ?? "(none)"}`);
20
21
  console.error("Run 'tx invariant --help' for usage information");
21
- process.exit(1);
22
+ throw new CliExitError(1);
22
23
  });
23
24
  }
24
25
  };
@@ -4,12 +4,12 @@
4
4
  import { Effect } from "effect";
5
5
  import { LearningService, FileLearningService, TaskService, RetrievalError } from "@jamesaphoenix/tx-core";
6
6
  import { type Flags } from "../utils/parse.js";
7
- export declare const learningAdd: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError, LearningService>;
7
+ export declare const learningAdd: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError, LearningService>;
8
8
  export declare const learningSearch: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | RetrievalError | import("@jamesaphoenix/tx-core").EmbeddingDimensionMismatchError, LearningService>;
9
9
  export declare const learningRecent: (_pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError, LearningService>;
10
- export declare const learningHelpful: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").LearningNotFoundError, LearningService>;
10
+ export declare const learningHelpful: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").LearningNotFoundError, LearningService>;
11
11
  export declare const context: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError | RetrievalError | import("@jamesaphoenix/tx-core").EmbeddingDimensionMismatchError, TaskService | LearningService>;
12
- export declare const learn: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError, FileLearningService>;
12
+ export declare const learn: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError, FileLearningService>;
13
13
  export declare const recall: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError, FileLearningService>;
14
14
  export declare const learningEmbed: (_pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError, LearningService>;
15
15
  export declare const learningHelp: (subcommand: string) => Effect.Effect<void, never, never>;
@@ -11,6 +11,7 @@ import { homedir } from "node:os";
11
11
  import { TaskService, buildClaudeTaskFiles } from "@jamesaphoenix/tx-core";
12
12
  import { toJson } from "../output.js";
13
13
  import { flag, opt } from "../utils/parse.js";
14
+ import { CliExitError } from "../cli-exit.js";
14
15
  export const syncClaude = (_pos, flags) => Effect.gen(function* () {
15
16
  const taskSvc = yield* TaskService;
16
17
  // Resolve target directory
@@ -21,7 +22,7 @@ export const syncClaude = (_pos, flags) => Effect.gen(function* () {
21
22
  // Validate team name to prevent path traversal (e.g. --team ../../.ssh)
22
23
  if (!/^[a-zA-Z0-9_-]+$/.test(teamName)) {
23
24
  console.error("Invalid team name: must contain only alphanumeric characters, hyphens, and underscores");
24
- process.exit(1);
25
+ throw new CliExitError(1);
25
26
  }
26
27
  targetDir = join(homedir(), ".claude", "tasks", teamName);
27
28
  }
@@ -30,7 +31,7 @@ export const syncClaude = (_pos, flags) => Effect.gen(function* () {
30
31
  }
31
32
  else {
32
33
  console.error("Either --team <name> or --dir <path> is required");
33
- process.exit(1);
34
+ throw new CliExitError(1);
34
35
  }
35
36
  // Create directory if it doesn't exist
36
37
  if (!existsSync(targetDir)) {
@@ -69,6 +70,6 @@ export const syncClaude = (_pos, flags) => Effect.gen(function* () {
69
70
  });
70
71
  export const syncCodex = (_pos, _flags) => Effect.sync(() => {
71
72
  console.error("Codex sync is not yet implemented. Use 'tx sync claude' for Claude Code.");
72
- process.exit(1);
73
+ throw new CliExitError(1);
73
74
  });
74
75
  //# sourceMappingURL=sync-platform.js.map
@@ -4,5 +4,5 @@
4
4
  import { Effect } from "effect";
5
5
  import { SyncService } from "@jamesaphoenix/tx-core";
6
6
  import { type Flags } from "../utils/parse.js";
7
- export declare const sync: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError, import("@jamesaphoenix/tx-core").TaskService | SyncService>;
7
+ export declare const sync: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").TaskNotFoundError, import("@jamesaphoenix/tx-core").TaskService | SyncService>;
8
8
  //# sourceMappingURL=sync.d.ts.map
@@ -6,6 +6,7 @@ import { SyncService } from "@jamesaphoenix/tx-core";
6
6
  import { toJson } from "../output.js";
7
7
  import { commandHelp } from "../help.js";
8
8
  import { flag, opt } from "../utils/parse.js";
9
+ import { CliExitError } from "../cli-exit.js";
9
10
  import { syncClaude, syncCodex } from "./sync-platform.js";
10
11
  export const sync = (pos, flags) => Effect.gen(function* () {
11
12
  const subcommand = pos[0];
@@ -79,7 +80,7 @@ export const sync = (pos, flags) => Effect.gen(function* () {
79
80
  const disableFlag = flag(flags, "disable");
80
81
  if (enableFlag && disableFlag) {
81
82
  console.error("Cannot specify both --enable and --disable");
82
- process.exit(1);
83
+ throw new CliExitError(1);
83
84
  }
84
85
  if (enableFlag) {
85
86
  yield* syncSvc.enableAutoSync();
@@ -122,7 +123,7 @@ export const sync = (pos, flags) => Effect.gen(function* () {
122
123
  else {
123
124
  console.error(`Unknown sync subcommand: ${subcommand}`);
124
125
  console.error(`Run 'tx sync --help' for usage information`);
125
- process.exit(1);
126
+ throw new CliExitError(1);
126
127
  }
127
128
  });
128
129
  //# sourceMappingURL=sync.js.map
@@ -4,12 +4,12 @@
4
4
  import { Effect } from "effect";
5
5
  import { TaskService, ReadyService, AttemptService } from "@jamesaphoenix/tx-core";
6
6
  import { type Flags } from "../utils/parse.js";
7
- export declare const add: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError, TaskService>;
7
+ export declare const add: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").TaskNotFoundError, TaskService>;
8
8
  export declare const list: (_pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError, TaskService>;
9
9
  export declare const ready: (_pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError, ReadyService | AttemptService>;
10
10
  export declare const show: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError, TaskService | AttemptService>;
11
- export declare const update: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").StaleDataError, TaskService>;
12
- export declare const done: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").StaleDataError, TaskService | ReadyService>;
11
+ export declare const update: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").StaleDataError, TaskService>;
12
+ export declare const done: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").StaleDataError, TaskService | ReadyService>;
13
13
  export declare const deleteTask: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").HasChildrenError, TaskService>;
14
- export declare const reset: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").StaleDataError, TaskService>;
14
+ export declare const reset: (pos: string[], flags: Flags) => Effect.Effect<void, import("@jamesaphoenix/tx-core").DatabaseError | import("@jamesaphoenix/tx-core").ValidationError | import("@jamesaphoenix/tx-core").TaskNotFoundError | import("@jamesaphoenix/tx-core").StaleDataError, TaskService>;
15
15
  //# sourceMappingURL=task.d.ts.map
@@ -6,11 +6,12 @@ import { TaskService, ReadyService, AttemptService } from "@jamesaphoenix/tx-cor
6
6
  import { assertTaskStatus, TASK_STATUSES } from "@jamesaphoenix/tx-types";
7
7
  import { toJson, formatTaskWithDeps, formatTaskLine, formatReadyTaskLine } from "../output.js";
8
8
  import { flag, opt, parseIntOpt, parseTaskId } from "../utils/parse.js";
9
+ import { CliExitError } from "../cli-exit.js";
9
10
  export const add = (pos, flags) => Effect.gen(function* () {
10
11
  const title = pos[0];
11
12
  if (!title) {
12
13
  console.error("Usage: tx add <title> [--parent/-p <id>] [--score/-s <n>] [--description/-d <text>] [--json]");
13
- process.exit(1);
14
+ throw new CliExitError(1);
14
15
  }
15
16
  const svc = yield* TaskService;
16
17
  const task = yield* svc.create({
@@ -44,7 +45,7 @@ export const list = (_pos, flags) => Effect.gen(function* () {
44
45
  }
45
46
  catch {
46
47
  console.error(`Invalid status filter. Valid statuses: ${TASK_STATUSES.join(", ")}`);
47
- process.exit(1);
48
+ throw new CliExitError(1);
48
49
  }
49
50
  }
50
51
  const tasks = yield* svc.listWithDeps({
@@ -100,7 +101,7 @@ export const show = (pos, flags) => Effect.gen(function* () {
100
101
  const raw = pos[0];
101
102
  if (!raw) {
102
103
  console.error("Usage: tx show <id> [--json]");
103
- process.exit(1);
104
+ throw new CliExitError(1);
104
105
  }
105
106
  const id = parseTaskId(raw);
106
107
  const svc = yield* TaskService;
@@ -133,7 +134,7 @@ export const update = (pos, flags) => Effect.gen(function* () {
133
134
  const raw = pos[0];
134
135
  if (!raw) {
135
136
  console.error("Usage: tx update <id> [--status <s>] [--title <t>] [--score <n>] [--description <d>] [--parent <p>] [--json]");
136
- process.exit(1);
137
+ throw new CliExitError(1);
137
138
  }
138
139
  const id = parseTaskId(raw);
139
140
  const svc = yield* TaskService;
@@ -164,7 +165,7 @@ export const done = (pos, flags) => Effect.gen(function* () {
164
165
  const raw = pos[0];
165
166
  if (!raw) {
166
167
  console.error("Usage: tx done <id> [--json]");
167
- process.exit(1);
168
+ throw new CliExitError(1);
168
169
  }
169
170
  const id = parseTaskId(raw);
170
171
  const taskSvc = yield* TaskService;
@@ -194,7 +195,7 @@ export const deleteTask = (pos, flags) => Effect.gen(function* () {
194
195
  const raw = pos[0];
195
196
  if (!raw) {
196
197
  console.error("Usage: tx delete <id> [--cascade] [--json]");
197
- process.exit(1);
198
+ throw new CliExitError(1);
198
199
  }
199
200
  const id = parseTaskId(raw);
200
201
  const cascade = flag(flags, "cascade");
@@ -212,7 +213,7 @@ export const reset = (pos, flags) => Effect.gen(function* () {
212
213
  const raw = pos[0];
213
214
  if (!raw) {
214
215
  console.error("Usage: tx reset <id> [--json]");
215
- process.exit(1);
216
+ throw new CliExitError(1);
216
217
  }
217
218
  const id = parseTaskId(raw);
218
219
  const taskSvc = yield* TaskService;