@clipboard-health/groundcrew 4.2.0 → 4.2.2

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 (70) hide show
  1. package/README.md +15 -25
  2. package/dist/commands/cleaner.d.ts +1 -1
  3. package/dist/commands/cleaner.d.ts.map +1 -1
  4. package/dist/commands/cleaner.js +4 -2
  5. package/dist/commands/dispatcher.d.ts +7 -6
  6. package/dist/commands/dispatcher.d.ts.map +1 -1
  7. package/dist/commands/dispatcher.js +56 -28
  8. package/dist/commands/doctor.d.ts.map +1 -1
  9. package/dist/commands/doctor.js +18 -22
  10. package/dist/commands/eligibility.d.ts +1 -1
  11. package/dist/commands/eligibility.d.ts.map +1 -1
  12. package/dist/commands/eligibility.js +7 -6
  13. package/dist/commands/orchestrator.d.ts.map +1 -1
  14. package/dist/commands/orchestrator.js +18 -14
  15. package/dist/commands/resumeWorkspace.d.ts.map +1 -1
  16. package/dist/commands/resumeWorkspace.js +3 -2
  17. package/dist/commands/setupWorkspace.d.ts +2 -4
  18. package/dist/commands/setupWorkspace.d.ts.map +1 -1
  19. package/dist/commands/setupWorkspace.js +27 -27
  20. package/dist/commands/status.d.ts.map +1 -1
  21. package/dist/commands/status.js +6 -3
  22. package/dist/index.d.ts +3 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -2
  25. package/dist/lib/adapters/linear/client.d.ts +22 -0
  26. package/dist/lib/adapters/linear/client.d.ts.map +1 -0
  27. package/dist/lib/adapters/linear/client.js +36 -0
  28. package/dist/lib/adapters/linear/factory.d.ts +24 -14
  29. package/dist/lib/adapters/linear/factory.d.ts.map +1 -1
  30. package/dist/lib/adapters/linear/factory.js +113 -46
  31. package/dist/lib/{boardSource.d.ts → adapters/linear/fetch.d.ts} +22 -74
  32. package/dist/lib/adapters/linear/fetch.d.ts.map +1 -0
  33. package/dist/lib/{boardSource.js → adapters/linear/fetch.js} +28 -136
  34. package/dist/lib/adapters/linear/index.d.ts +1 -0
  35. package/dist/lib/adapters/linear/index.d.ts.map +1 -1
  36. package/dist/lib/adapters/linear/parsing.d.ts +44 -0
  37. package/dist/lib/adapters/linear/parsing.d.ts.map +1 -0
  38. package/dist/lib/adapters/linear/parsing.js +144 -0
  39. package/dist/lib/{linearIssueStatus.d.ts → adapters/linear/writeback.d.ts} +1 -2
  40. package/dist/lib/adapters/linear/writeback.d.ts.map +1 -0
  41. package/dist/lib/{linearIssueStatus.js → adapters/linear/writeback.js} +16 -17
  42. package/dist/lib/adapters/shell/factory.d.ts +1 -1
  43. package/dist/lib/adapters/shell/factory.d.ts.map +1 -1
  44. package/dist/lib/adapters/shell/factory.js +8 -4
  45. package/dist/lib/adapters/shell/invoke.d.ts +4 -7
  46. package/dist/lib/adapters/shell/invoke.d.ts.map +1 -1
  47. package/dist/lib/adapters/shell/invoke.js +46 -75
  48. package/dist/lib/adapters/shell/schema.d.ts +10 -0
  49. package/dist/lib/adapters/shell/schema.d.ts.map +1 -1
  50. package/dist/lib/adapters/shell/schema.js +9 -5
  51. package/dist/lib/board.d.ts.map +1 -1
  52. package/dist/lib/board.js +43 -4
  53. package/dist/lib/buildSources.d.ts +11 -0
  54. package/dist/lib/buildSources.d.ts.map +1 -1
  55. package/dist/lib/buildSources.js +41 -0
  56. package/dist/lib/repositoryValidation.d.ts +13 -0
  57. package/dist/lib/repositoryValidation.d.ts.map +1 -0
  58. package/dist/lib/repositoryValidation.js +20 -0
  59. package/dist/lib/testing/canonicalFixtures.d.ts +19 -0
  60. package/dist/lib/testing/canonicalFixtures.d.ts.map +1 -0
  61. package/dist/lib/testing/canonicalFixtures.js +62 -0
  62. package/dist/lib/ticketSource.d.ts +73 -3
  63. package/dist/lib/ticketSource.d.ts.map +1 -1
  64. package/dist/lib/ticketSource.js +31 -0
  65. package/dist/lib/util.d.ts +0 -20
  66. package/dist/lib/util.d.ts.map +1 -1
  67. package/dist/lib/util.js +0 -35
  68. package/package.json +1 -1
  69. package/dist/lib/boardSource.d.ts.map +0 -1
  70. package/dist/lib/linearIssueStatus.d.ts.map +0 -1
@@ -0,0 +1,62 @@
1
+ import { toCanonicalId } from "../ticketSource.js";
2
+ export function canonicalLinearIssue(overrides) {
3
+ const { naturalId, sourceRef: refOverride, ...rest } = overrides;
4
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- test fixture; sourceRef is opaque unknown in the Issue contract; we reinterpret it here only for fixture construction
5
+ const refPartial = refOverride ?? {};
6
+ const sourceRef = {
7
+ uuid: refPartial.uuid ?? `uuid-${naturalId}`,
8
+ statusId: refPartial.statusId ?? "statusId-default",
9
+ teamId: refPartial.teamId ?? "team-default",
10
+ stateType: refPartial.stateType ?? "unstarted",
11
+ nativeStatus: refPartial.nativeStatus ?? "Todo",
12
+ };
13
+ return {
14
+ id: toCanonicalId("linear", naturalId),
15
+ source: "linear",
16
+ title: `Title for ${naturalId}`,
17
+ description: "",
18
+ status: "todo",
19
+ repository: undefined,
20
+ model: undefined,
21
+ assignee: "Unassigned",
22
+ updatedAt: "2026-01-01T00:00:00.000Z",
23
+ blockers: [],
24
+ hasMoreBlockers: false,
25
+ ...rest,
26
+ sourceRef,
27
+ };
28
+ }
29
+ export function canonicalBlocker(overrides) {
30
+ const { naturalId, ...rest } = overrides;
31
+ return {
32
+ id: toCanonicalId("linear", naturalId),
33
+ title: `Title for ${naturalId}`,
34
+ status: "todo",
35
+ ...rest,
36
+ };
37
+ }
38
+ /**
39
+ * Canonical Issue fixture for a non-Linear source. Default source name is
40
+ * "shell-test"; override via `sourceName`. Mirrors `canonicalLinearIssue`'s
41
+ * defaults except `sourceRef` is an empty opaque object (no LinearSourceRef
42
+ * shape, since this is meant to stand in for any non-Linear adapter — the
43
+ * shell adapter, future Jira adapter, etc.).
44
+ */
45
+ export function canonicalShellIssue(overrides) {
46
+ const { naturalId, sourceName = "shell-test", sourceRef, ...rest } = overrides;
47
+ return {
48
+ id: toCanonicalId(sourceName, naturalId),
49
+ source: sourceName,
50
+ title: `Title for ${naturalId}`,
51
+ description: "",
52
+ status: "todo",
53
+ repository: undefined,
54
+ model: undefined,
55
+ assignee: "Unassigned",
56
+ updatedAt: "2026-01-01T00:00:00.000Z",
57
+ blockers: [],
58
+ hasMoreBlockers: false,
59
+ sourceRef: sourceRef ?? {},
60
+ ...rest,
61
+ };
62
+ }
@@ -26,18 +26,42 @@ export interface Blocker {
26
26
  id: string;
27
27
  title: string;
28
28
  status: CanonicalStatus;
29
+ /**
30
+ * When `status === "other"`, adapters MUST set this to explain why
31
+ * they couldn't classify. Consumers (specifically `ticketDoctor`) render
32
+ * this verbatim to give users an actionable next step.
33
+ *
34
+ * - `"missing"`: the source returned no status for this blocker
35
+ * (e.g., Linear had no state on the blocker; shell script omitted
36
+ * the field).
37
+ * - `"unmapped"`: the source returned a status that isn't in the
38
+ * source's known mapping (e.g., a Linear column not in
39
+ * `linear.projects[*].statuses`, or an unrecognized shell value).
40
+ *
41
+ * MUST be undefined when `status !== "other"`.
42
+ */
43
+ statusReason?: "missing" | "unmapped";
44
+ /**
45
+ * Human-readable native status from the source, when available.
46
+ * Used for diagnostic display only — never branched on. Adapters SHOULD
47
+ * populate this when `statusReason === "unmapped"` so users can see
48
+ * which status name to add to their config; MAY populate for mapped
49
+ * statuses too if the source's native vocabulary differs usefully
50
+ * from `CanonicalStatus`.
51
+ */
52
+ nativeStatus?: string;
29
53
  }
30
54
  export interface Issue {
31
- /** Canonical, source-prefixed id, e.g. "linear:eng-220" or "shell-jira:HRD-1". */
55
+ /** Canonical, source-prefixed id, e.g. "linear:eng-220" or "shell-jira:hrd-1". */
32
56
  id: string;
33
57
  /** Source name (the adapter's `name`, defaulting to its `kind`). */
34
58
  source: string;
35
59
  title: string;
36
60
  description: string;
37
61
  status: CanonicalStatus;
38
- /** `undefined` when the ticket isn't groundcrew-eligible (no agent label / no repo match). */
62
+ /** `undefined` when the ticket is not dispatchable to a repository. */
39
63
  repository: string | undefined;
40
- /** `undefined` when the ticket isn't groundcrew-eligible. */
64
+ /** Parsed agent model when the source can resolve one; may be present on non-Todo tickets for logs. */
41
65
  model: string | undefined;
42
66
  assignee: string;
43
67
  updatedAt: string;
@@ -52,9 +76,26 @@ export type GroundcrewIssue = Issue & {
52
76
  repository: string;
53
77
  };
54
78
  export declare function isGroundcrewIssue(issue: Issue): issue is GroundcrewIssue;
79
+ /**
80
+ * A parent ticket that was dropped from the fetch result because it has
81
+ * sub-issues. Surfaced separately so the dispatcher can log WHY a
82
+ * Todo+labelled ticket wasn't picked up (PR #80 behavior).
83
+ */
84
+ export interface ParentSkip {
85
+ /**
86
+ * Canonical, source-prefixed id, e.g. "linear:eng-220". Matches the form
87
+ * used by `Issue.id` so consumers can treat all ids uniformly and strip
88
+ * the prefix with `naturalIdFromCanonical` when displaying to operators.
89
+ */
90
+ id: string;
91
+ title: string;
92
+ childCount: number;
93
+ }
55
94
  export interface BoardState {
56
95
  timestamp: string;
57
96
  issues: Issue[];
97
+ /** Parent tickets skipped because they have sub-issues. */
98
+ parentSkips: readonly ParentSkip[];
58
99
  }
59
100
  export interface TicketSource {
60
101
  /** Stable identifier used as the id prefix and in log lines. Equal to the source's config `name`. */
@@ -67,6 +108,13 @@ export interface TicketSource {
67
108
  resolveOne(naturalId: string): Promise<Issue | undefined>;
68
109
  /** Writeback. The adapter downcasts `issue.sourceRef` internally. */
69
110
  markInProgress(issue: Issue): Promise<void>;
111
+ /**
112
+ * Optional: return parent tickets that were excluded from `fetch()` because
113
+ * they have sub-issues. Board surfaces these so the dispatcher can log WHY
114
+ * a Todo+labelled ticket was skipped (PR #80 behavior). Adapters that
115
+ * don't distinguish parents simply omit this method; Board returns [].
116
+ */
117
+ fetchParentSkips?(): Promise<readonly ParentSkip[]>;
70
118
  }
71
119
  export declare class RepositoryResolutionError extends Error {
72
120
  constructor(arguments_: {
@@ -80,4 +128,26 @@ export declare class AmbiguousTicketError extends Error {
80
128
  matches: readonly string[];
81
129
  });
82
130
  }
131
+ /**
132
+ * Build a canonical source-prefixed id from a source name and a natural
133
+ * (possibly mixed-case) id. Lower-cases the natural part so the same
134
+ * ticket always produces the same canonical id regardless of which code
135
+ * path or adapter constructed it.
136
+ *
137
+ * All adapters MUST use this helper when constructing canonical ids
138
+ * (rather than concatenating `${sourceName}:${naturalId}` inline) so
139
+ * that `Board.resolveOne` lookups against lower-cased natural-id input
140
+ * find the issue regardless of the casing the source emitted.
141
+ */
142
+ export declare function toCanonicalId(sourceName: string, naturalId: string): string;
143
+ /**
144
+ * Strip the source prefix from a canonical id, yielding the natural id
145
+ * the producing adapter exposed. Use at consumer boundaries where you
146
+ * need to compare a canonical id against natural-id artifacts like
147
+ * `WorktreeEntry.ticket` or filesystem directory names.
148
+ *
149
+ * Canonical ids always carry a `<source>:` prefix; the no-colon branch
150
+ * is a defensive fallback that's unreachable in normal operation.
151
+ */
152
+ export declare function naturalIdFromCanonical(id: string): string;
83
153
  //# sourceMappingURL=ticketSource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ticketSource.d.ts","sourceRoot":"","sources":["../../src/lib/ticketSource.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,aAAa,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtF,MAAM,WAAW,OAAO;IACtB,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,KAAK;IACpB,kFAAkF;IAClF,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,CAAC;IACxB,8FAA8F;IAC9F,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,wFAAwF;IACxF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,mEAAmE;AACnE,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,IAAI,eAAe,CAExE;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,qGAAqG;IACrG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,oFAAoF;IACpF,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1B,0EAA0E;IAC1E,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IAC1D,qEAAqE;IACrE,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,YAAmB,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAMjF;CACF;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAmB,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAM/E;CACF"}
1
+ {"version":3,"file":"ticketSource.d.ts","sourceRoot":"","sources":["../../src/lib/ticketSource.ts"],"names":[],"mappings":"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"}
@@ -24,3 +24,34 @@ export class AmbiguousTicketError extends Error {
24
24
  this.name = "AmbiguousTicketError";
25
25
  }
26
26
  }
27
+ /**
28
+ * Build a canonical source-prefixed id from a source name and a natural
29
+ * (possibly mixed-case) id. Lower-cases the natural part so the same
30
+ * ticket always produces the same canonical id regardless of which code
31
+ * path or adapter constructed it.
32
+ *
33
+ * All adapters MUST use this helper when constructing canonical ids
34
+ * (rather than concatenating `${sourceName}:${naturalId}` inline) so
35
+ * that `Board.resolveOne` lookups against lower-cased natural-id input
36
+ * find the issue regardless of the casing the source emitted.
37
+ */
38
+ export function toCanonicalId(sourceName, naturalId) {
39
+ return `${sourceName}:${naturalId.toLowerCase()}`;
40
+ }
41
+ /**
42
+ * Strip the source prefix from a canonical id, yielding the natural id
43
+ * the producing adapter exposed. Use at consumer boundaries where you
44
+ * need to compare a canonical id against natural-id artifacts like
45
+ * `WorktreeEntry.ticket` or filesystem directory names.
46
+ *
47
+ * Canonical ids always carry a `<source>:` prefix; the no-colon branch
48
+ * is a defensive fallback that's unreachable in normal operation.
49
+ */
50
+ export function naturalIdFromCanonical(id) {
51
+ const colonIndex = id.indexOf(":");
52
+ /* v8 ignore next @preserve -- canonical ids always carry a source prefix; this branch is unreachable */
53
+ if (colonIndex === -1) {
54
+ return id;
55
+ }
56
+ return id.slice(colonIndex + 1);
57
+ }
@@ -1,4 +1,3 @@
1
- import { LinearClient } from "@linear/sdk";
2
1
  export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
3
2
  export declare function writeOutput(message?: string): void;
4
3
  export declare function writeError(message: string): void;
@@ -8,25 +7,6 @@ export declare function log(message: string): void;
8
7
  type LogEventFieldValue = boolean | number | string | readonly string[] | undefined;
9
8
  export declare function logEvent(event: string, fields: Record<string, LogEventFieldValue>): void;
10
9
  export declare function readEnvironmentVariable(name: string): string | undefined;
11
- declare const LINEAR_API_KEY_SOURCES: readonly ["GROUNDCREW_LINEAR_API_KEY", "LINEAR_API_KEY"];
12
- export type LinearApiKeySource = (typeof LINEAR_API_KEY_SOURCES)[number];
13
- export interface ResolvedLinearApiKey {
14
- value: string;
15
- source: LinearApiKeySource;
16
- }
17
- export declare function resolveLinearApiKey(): ResolvedLinearApiKey | undefined;
18
- export declare function getLinearClient(): LinearClient;
19
- /**
20
- * Returns a zero-arg getter that lazily constructs (and caches) a Linear
21
- * client on first call. Used by CLI entry points that may not need the
22
- * client at all, so we avoid blowing up on a missing API key when no Linear
23
- * call is actually made. The factory is taken as a
24
- * parameter (rather than calling `getLinearClient` directly) so callers can
25
- * pass their own module-level import of `getLinearClient` — that binding
26
- * respects `vi.mock` intercepts, whereas an intra-module reference would
27
- * not.
28
- */
29
- export declare function lazyLinearClient(factory: () => LinearClient): () => LinearClient;
30
10
  /**
31
11
  * Reads the value that follows `--ticket` at `argv[index + 1]`. Throws a
32
12
  * uniform "ticket id is required" error if the value is missing, empty, or
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/lib/util.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3E;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAIlD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGhD;AAQD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEzD;AAED,wBAAsB,uBAAuB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxF;AAkBD,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAQzC;AAED,KAAK,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;AAUpF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAcxF;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGxE;AAED,QAAA,MAAM,sBAAsB,YAAI,2BAA2B,EAAE,gBAAgB,CAAU,CAAC;AAExF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,wBAAgB,mBAAmB,IAAI,oBAAoB,GAAG,SAAS,CAQtE;AAED,wBAAgB,eAAe,IAAI,YAAY,CAQ9C;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,YAAY,GAAG,MAAM,YAAY,CAMhF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMzF;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAcvF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAcnD"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/lib/util.ts"],"names":[],"mappings":"AAGA,wBAAsB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3E;AAED,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAIlD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGhD;AAQD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEzD;AAED,wBAAsB,uBAAuB,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxF;AAkBD,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAQzC;AAED,KAAK,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;AAUpF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAcxF;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGxE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMzF;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAcvF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAcnD"}
package/dist/lib/util.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { appendFileSync, mkdirSync } from "node:fs";
2
2
  import { dirname } from "node:path";
3
- import { LinearClient } from "@linear/sdk";
4
3
  export async function sleep(ms, signal) {
5
4
  if (signal?.aborted === true) {
6
5
  return;
@@ -99,40 +98,6 @@ export function readEnvironmentVariable(name) {
99
98
  // oxlint-disable-next-line node/no-process-env -- Centralized environment accessor.
100
99
  return process.env[name];
101
100
  }
102
- const LINEAR_API_KEY_SOURCES = ["GROUNDCREW_LINEAR_API_KEY", "LINEAR_API_KEY"];
103
- export function resolveLinearApiKey() {
104
- for (const source of LINEAR_API_KEY_SOURCES) {
105
- const value = readEnvironmentVariable(source);
106
- if (value !== undefined && value.length > 0) {
107
- return { value, source };
108
- }
109
- }
110
- return undefined;
111
- }
112
- export function getLinearClient() {
113
- const resolved = resolveLinearApiKey();
114
- if (resolved === undefined) {
115
- throw new Error("Linear API key not set. Set GROUNDCREW_LINEAR_API_KEY or LINEAR_API_KEY in your environment.");
116
- }
117
- return new LinearClient({ apiKey: resolved.value });
118
- }
119
- /**
120
- * Returns a zero-arg getter that lazily constructs (and caches) a Linear
121
- * client on first call. Used by CLI entry points that may not need the
122
- * client at all, so we avoid blowing up on a missing API key when no Linear
123
- * call is actually made. The factory is taken as a
124
- * parameter (rather than calling `getLinearClient` directly) so callers can
125
- * pass their own module-level import of `getLinearClient` — that binding
126
- * respects `vi.mock` intercepts, whereas an intra-module reference would
127
- * not.
128
- */
129
- export function lazyLinearClient(factory) {
130
- let client;
131
- return () => {
132
- client ??= factory();
133
- return client;
134
- };
135
- }
136
101
  /**
137
102
  * Reads the value that follows `--ticket` at `argv[index + 1]`. Throws a
138
103
  * uniform "ticket id is required" error if the value is missing, empty, or
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clipboard-health/groundcrew",
3
- "version": "4.2.0",
3
+ "version": "4.2.2",
4
4
  "description": "Linear-driven orchestrator that launches AI coding agents in git worktrees, with workspace lifecycle and usage tracking.",
5
5
  "keywords": [
6
6
  "agent",
@@ -1 +0,0 @@
1
- {"version":3,"file":"boardSource.d.ts","sourceRoot":"","sources":["../../src/lib/boardSource.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"linearIssueStatus.d.ts","sourceRoot":"","sources":["../../src/lib/linearIssueStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAIhD,UAAU,oBAAoB;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,wBAAwB;IAChC,cAAc,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,2BAA2B,IAAI,IAAI,CAAC;CACrC;AAED,wBAAgB,8BAA8B,CAAC,UAAU,EAAE;IACzD,MAAM,EAAE,YAAY,CAAC;CACtB,GAAG,wBAAwB,CAmD3B"}