@proletariat/cli 0.3.58 → 0.3.60

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 (212) hide show
  1. package/dist/commands/{spec → dashboard}/index.d.ts +4 -4
  2. package/dist/commands/dashboard/index.js +117 -0
  3. package/dist/commands/dashboard/index.js.map +1 -0
  4. package/dist/commands/execution/config.js +5 -4
  5. package/dist/commands/execution/config.js.map +1 -1
  6. package/dist/commands/execution/stop.js +4 -2
  7. package/dist/commands/execution/stop.js.map +1 -1
  8. package/dist/commands/execution/view.js +3 -0
  9. package/dist/commands/execution/view.js.map +1 -1
  10. package/dist/commands/init.d.ts +1 -0
  11. package/dist/commands/init.js +40 -3
  12. package/dist/commands/init.js.map +1 -1
  13. package/dist/commands/mcp-server.js +1 -2
  14. package/dist/commands/mcp-server.js.map +1 -1
  15. package/dist/commands/{spec/link/index.d.ts → session/exec.d.ts} +5 -3
  16. package/dist/commands/session/exec.js +205 -0
  17. package/dist/commands/session/exec.js.map +1 -0
  18. package/dist/commands/session/index.js +12 -0
  19. package/dist/commands/session/index.js.map +1 -1
  20. package/dist/commands/{spec/delete.d.ts → session/inspect.d.ts} +3 -3
  21. package/dist/commands/session/inspect.js +316 -0
  22. package/dist/commands/session/inspect.js.map +1 -0
  23. package/dist/commands/session/peek.d.ts +15 -0
  24. package/dist/commands/session/peek.js +141 -8
  25. package/dist/commands/session/peek.js.map +1 -1
  26. package/dist/commands/session/poke.d.ts +4 -1
  27. package/dist/commands/session/poke.js +175 -20
  28. package/dist/commands/session/poke.js.map +1 -1
  29. package/dist/commands/{spec/link/depends.d.ts → session/restart.d.ts} +6 -4
  30. package/dist/commands/session/restart.js +320 -0
  31. package/dist/commands/session/restart.js.map +1 -0
  32. package/dist/commands/ticket/list.d.ts +10 -0
  33. package/dist/commands/ticket/list.js +126 -1
  34. package/dist/commands/ticket/list.js.map +1 -1
  35. package/dist/commands/tools/add.d.ts +20 -0
  36. package/dist/commands/tools/add.js +129 -0
  37. package/dist/commands/tools/add.js.map +1 -0
  38. package/dist/commands/tools/check.d.ts +10 -0
  39. package/dist/commands/tools/check.js +75 -0
  40. package/dist/commands/tools/check.js.map +1 -0
  41. package/dist/commands/tools/detect.d.ts +11 -0
  42. package/dist/commands/tools/detect.js +107 -0
  43. package/dist/commands/tools/detect.js.map +1 -0
  44. package/dist/commands/tools/index.d.ts +11 -0
  45. package/dist/commands/tools/index.js +87 -0
  46. package/dist/commands/tools/index.js.map +1 -0
  47. package/dist/commands/tools/remove.d.ts +13 -0
  48. package/dist/commands/tools/remove.js +55 -0
  49. package/dist/commands/tools/remove.js.map +1 -0
  50. package/dist/commands/{spec/view.d.ts → trello/configure.d.ts} +6 -6
  51. package/dist/commands/trello/configure.js +259 -0
  52. package/dist/commands/trello/configure.js.map +1 -0
  53. package/dist/commands/{spec/plan.d.ts → trello/import.d.ts} +3 -5
  54. package/dist/commands/trello/import.js +241 -0
  55. package/dist/commands/trello/import.js.map +1 -0
  56. package/dist/commands/{spec/ticket.d.ts → trello/sync.d.ts} +5 -6
  57. package/dist/commands/trello/sync.js +190 -0
  58. package/dist/commands/trello/sync.js.map +1 -0
  59. package/dist/commands/work/start.d.ts +1 -0
  60. package/dist/commands/work/start.js +17 -39
  61. package/dist/commands/work/start.js.map +1 -1
  62. package/dist/lib/dashboard/data.d.ts +64 -0
  63. package/dist/lib/dashboard/data.js +259 -0
  64. package/dist/lib/dashboard/data.js.map +1 -0
  65. package/dist/lib/dashboard/html.d.ts +7 -0
  66. package/dist/lib/dashboard/html.js +682 -0
  67. package/dist/lib/dashboard/html.js.map +1 -0
  68. package/dist/lib/dashboard/server.d.ts +20 -0
  69. package/dist/lib/dashboard/server.js +114 -0
  70. package/dist/lib/dashboard/server.js.map +1 -0
  71. package/dist/lib/events/events.d.ts +26 -2
  72. package/dist/lib/events/events.js +3 -2
  73. package/dist/lib/events/events.js.map +1 -1
  74. package/dist/lib/execution/config.d.ts +8 -0
  75. package/dist/lib/execution/config.js +83 -4
  76. package/dist/lib/execution/config.js.map +1 -1
  77. package/dist/lib/execution/runners.d.ts +36 -3
  78. package/dist/lib/execution/runners.js +216 -35
  79. package/dist/lib/execution/runners.js.map +1 -1
  80. package/dist/lib/execution/spawner.d.ts +2 -0
  81. package/dist/lib/execution/spawner.js +22 -31
  82. package/dist/lib/execution/spawner.js.map +1 -1
  83. package/dist/lib/execution/types.d.ts +26 -5
  84. package/dist/lib/execution/types.js +24 -0
  85. package/dist/lib/execution/types.js.map +1 -1
  86. package/dist/lib/external-issues/adapters.d.ts +17 -0
  87. package/dist/lib/external-issues/adapters.js +88 -0
  88. package/dist/lib/external-issues/adapters.js.map +1 -1
  89. package/dist/lib/external-issues/index.d.ts +1 -0
  90. package/dist/lib/external-issues/index.js +2 -0
  91. package/dist/lib/external-issues/index.js.map +1 -1
  92. package/dist/lib/external-issues/mapping-store.js +1 -1
  93. package/dist/lib/external-issues/outbound-sync.d.ts +79 -0
  94. package/dist/lib/external-issues/outbound-sync.js +296 -0
  95. package/dist/lib/external-issues/outbound-sync.js.map +1 -0
  96. package/dist/lib/external-issues/trello.d.ts +80 -0
  97. package/dist/lib/external-issues/trello.js +266 -0
  98. package/dist/lib/external-issues/trello.js.map +1 -0
  99. package/dist/lib/external-issues/types.d.ts +3 -3
  100. package/dist/lib/external-issues/types.js +1 -1
  101. package/dist/lib/external-issues/types.js.map +1 -1
  102. package/dist/lib/linear/client.d.ts +4 -3
  103. package/dist/lib/linear/client.js +185 -122
  104. package/dist/lib/linear/client.js.map +1 -1
  105. package/dist/lib/mcp/tools/cli-passthrough.js +77 -0
  106. package/dist/lib/mcp/tools/cli-passthrough.js.map +1 -1
  107. package/dist/lib/mcp/tools/index.d.ts +0 -1
  108. package/dist/lib/mcp/tools/index.js +0 -1
  109. package/dist/lib/mcp/tools/index.js.map +1 -1
  110. package/dist/lib/onboarding/detect-tools.d.ts +15 -0
  111. package/dist/lib/onboarding/detect-tools.js +44 -0
  112. package/dist/lib/onboarding/detect-tools.js.map +1 -0
  113. package/dist/lib/onboarding/index.d.ts +2 -0
  114. package/dist/lib/onboarding/index.js +3 -0
  115. package/dist/lib/onboarding/index.js.map +1 -0
  116. package/dist/lib/onboarding/wizard.d.ts +25 -0
  117. package/dist/lib/onboarding/wizard.js +156 -0
  118. package/dist/lib/onboarding/wizard.js.map +1 -0
  119. package/dist/lib/pmo/schema.d.ts +2 -1
  120. package/dist/lib/pmo/schema.js +3 -1
  121. package/dist/lib/pmo/schema.js.map +1 -1
  122. package/dist/lib/pmo/storage/tickets.d.ts +8 -0
  123. package/dist/lib/pmo/storage/tickets.js +56 -2
  124. package/dist/lib/pmo/storage/tickets.js.map +1 -1
  125. package/dist/lib/pmo/sync-manager.js +3 -0
  126. package/dist/lib/pmo/sync-manager.js.map +1 -1
  127. package/dist/lib/runners/claude-code-runner.js +6 -0
  128. package/dist/lib/runners/claude-code-runner.js.map +1 -1
  129. package/dist/lib/tool-registry/detect.d.ts +20 -0
  130. package/dist/lib/tool-registry/detect.js +95 -0
  131. package/dist/lib/tool-registry/detect.js.map +1 -0
  132. package/dist/lib/tool-registry/index.d.ts +10 -0
  133. package/dist/lib/tool-registry/index.js +13 -0
  134. package/dist/lib/tool-registry/index.js.map +1 -0
  135. package/dist/lib/tool-registry/policy.d.ts +32 -0
  136. package/dist/lib/tool-registry/policy.js +97 -0
  137. package/dist/lib/tool-registry/policy.js.map +1 -0
  138. package/dist/lib/tool-registry/registry.d.ts +42 -0
  139. package/dist/lib/tool-registry/registry.js +120 -0
  140. package/dist/lib/tool-registry/registry.js.map +1 -0
  141. package/dist/lib/tool-registry/spawn.d.ts +50 -0
  142. package/dist/lib/tool-registry/spawn.js +103 -0
  143. package/dist/lib/tool-registry/spawn.js.map +1 -0
  144. package/dist/lib/tool-registry/types.d.ts +56 -0
  145. package/dist/lib/tool-registry/types.js +109 -0
  146. package/dist/lib/tool-registry/types.js.map +1 -0
  147. package/dist/lib/trello/client.d.ts +23 -0
  148. package/dist/lib/trello/client.js +114 -0
  149. package/dist/lib/trello/client.js.map +1 -0
  150. package/dist/lib/trello/config.d.ts +55 -0
  151. package/dist/lib/trello/config.js +127 -0
  152. package/dist/lib/trello/config.js.map +1 -0
  153. package/dist/lib/trello/index.d.ts +5 -0
  154. package/dist/lib/trello/index.js +5 -0
  155. package/dist/lib/trello/index.js.map +1 -0
  156. package/dist/lib/trello/mapper.d.ts +13 -0
  157. package/dist/lib/trello/mapper.js +71 -0
  158. package/dist/lib/trello/mapper.js.map +1 -0
  159. package/dist/lib/trello/sync.d.ts +13 -0
  160. package/dist/lib/trello/sync.js +38 -0
  161. package/dist/lib/trello/sync.js.map +1 -0
  162. package/dist/lib/trello/types.d.ts +53 -0
  163. package/dist/lib/trello/types.js +2 -0
  164. package/dist/lib/trello/types.js.map +1 -0
  165. package/dist/lib/work-source/client.js +17 -0
  166. package/dist/lib/work-source/client.js.map +1 -1
  167. package/dist/lib/work-source/config.d.ts +1 -1
  168. package/dist/lib/work-source/config.js +23 -1
  169. package/dist/lib/work-source/config.js.map +1 -1
  170. package/dist/lib/work-source/index.d.ts +1 -0
  171. package/dist/lib/work-source/index.js +1 -0
  172. package/dist/lib/work-source/index.js.map +1 -1
  173. package/dist/lib/work-source/provider-sources.d.ts +113 -0
  174. package/dist/lib/work-source/provider-sources.js +227 -0
  175. package/dist/lib/work-source/provider-sources.js.map +1 -0
  176. package/oclif.manifest.json +4368 -4364
  177. package/package.json +6 -2
  178. package/dist/commands/spec/create.d.ts +0 -20
  179. package/dist/commands/spec/create.js +0 -171
  180. package/dist/commands/spec/create.js.map +0 -1
  181. package/dist/commands/spec/delete.js +0 -112
  182. package/dist/commands/spec/delete.js.map +0 -1
  183. package/dist/commands/spec/edit.d.ts +0 -23
  184. package/dist/commands/spec/edit.js +0 -262
  185. package/dist/commands/spec/edit.js.map +0 -1
  186. package/dist/commands/spec/index.js +0 -88
  187. package/dist/commands/spec/index.js.map +0 -1
  188. package/dist/commands/spec/link/depends.js +0 -87
  189. package/dist/commands/spec/link/depends.js.map +0 -1
  190. package/dist/commands/spec/link/index.js +0 -93
  191. package/dist/commands/spec/link/index.js.map +0 -1
  192. package/dist/commands/spec/link/remove.d.ts +0 -18
  193. package/dist/commands/spec/link/remove.js +0 -91
  194. package/dist/commands/spec/link/remove.js.map +0 -1
  195. package/dist/commands/spec/list.d.ts +0 -14
  196. package/dist/commands/spec/list.js +0 -101
  197. package/dist/commands/spec/list.js.map +0 -1
  198. package/dist/commands/spec/plan.js +0 -102
  199. package/dist/commands/spec/plan.js.map +0 -1
  200. package/dist/commands/spec/ticket.js +0 -144
  201. package/dist/commands/spec/ticket.js.map +0 -1
  202. package/dist/commands/spec/view.js +0 -202
  203. package/dist/commands/spec/view.js.map +0 -1
  204. package/dist/lib/mcp/tools/spec.d.ts +0 -6
  205. package/dist/lib/mcp/tools/spec.js +0 -197
  206. package/dist/lib/mcp/tools/spec.js.map +0 -1
  207. package/dist/lib/pmo/spec-parser.d.ts +0 -25
  208. package/dist/lib/pmo/spec-parser.js +0 -206
  209. package/dist/lib/pmo/spec-parser.js.map +0 -1
  210. package/dist/lib/pmo/spec-types.d.ts +0 -43
  211. package/dist/lib/pmo/spec-types.js +0 -8
  212. package/dist/lib/pmo/spec-types.js.map +0 -1
@@ -0,0 +1,296 @@
1
+ /**
2
+ * Outbound Sync Handler
3
+ *
4
+ * Listens for ticket state changes on the EventBus and pushes them
5
+ * to external issue trackers (Linear, Shortcut, etc.) via their
6
+ * respective adapters.
7
+ *
8
+ * The handler is provider-agnostic: it resolves which external provider
9
+ * a ticket is mapped to, then dispatches to the correct sync implementation.
10
+ */
11
+ import { getEventBus } from '../events/event-bus.js';
12
+ import { LinearClient } from '../linear/client.js';
13
+ import { LinearMapper } from '../linear/mapper.js';
14
+ import { LinearSync } from '../linear/sync.js';
15
+ import { loadLinearConfig, isLinearConfigured } from '../linear/config.js';
16
+ import { ExternalExecutionMappingStore } from './mapping-store.js';
17
+ /**
18
+ * OutboundSyncHandler subscribes to ticket events and pushes changes
19
+ * to mapped external providers. It is fire-and-forget: sync failures
20
+ * are logged but never block the caller.
21
+ */
22
+ export class OutboundSyncHandler {
23
+ unsubscribers = [];
24
+ db;
25
+ mappingStore;
26
+ constructor(db) {
27
+ this.db = db;
28
+ this.mappingStore = new ExternalExecutionMappingStore(db);
29
+ }
30
+ /**
31
+ * Start listening for ticket events on the global EventBus.
32
+ * Call `stop()` to unsubscribe.
33
+ */
34
+ start() {
35
+ const bus = getEventBus();
36
+ this.unsubscribers.push(bus.on('ticket:status_changed', (event) => {
37
+ void this.handleStatusChanged(event);
38
+ }));
39
+ this.unsubscribers.push(bus.on('ticket:pr_linked', (event) => {
40
+ void this.handlePRLinked(event);
41
+ }));
42
+ }
43
+ /**
44
+ * Stop listening for events and clean up.
45
+ */
46
+ stop() {
47
+ for (const unsub of this.unsubscribers) {
48
+ unsub();
49
+ }
50
+ this.unsubscribers = [];
51
+ }
52
+ /**
53
+ * Handle a ticket status change by syncing to all mapped external providers.
54
+ */
55
+ async handleStatusChanged(event) {
56
+ const results = [];
57
+ // Try Linear sync (via Linear-specific mapping table)
58
+ try {
59
+ const linearResult = await this.syncStatusToLinear(event);
60
+ if (linearResult) {
61
+ results.push(linearResult);
62
+ }
63
+ }
64
+ catch {
65
+ // Sync errors are non-fatal
66
+ }
67
+ // Try provider-agnostic sync via external_execution_map
68
+ try {
69
+ const genericResults = await this.syncStatusToMappedProviders(event);
70
+ results.push(...genericResults);
71
+ }
72
+ catch {
73
+ // Sync errors are non-fatal
74
+ }
75
+ return results;
76
+ }
77
+ /**
78
+ * Handle a PR link by syncing to all mapped external providers.
79
+ */
80
+ async handlePRLinked(event) {
81
+ const results = [];
82
+ // Try Linear sync
83
+ try {
84
+ const linearResult = await this.syncPRToLinear(event);
85
+ if (linearResult) {
86
+ results.push(linearResult);
87
+ }
88
+ }
89
+ catch {
90
+ // Sync errors are non-fatal
91
+ }
92
+ // Update provider-agnostic mapping with PR URL
93
+ try {
94
+ this.recordPRInMappings(event);
95
+ }
96
+ catch {
97
+ // Non-fatal
98
+ }
99
+ return results;
100
+ }
101
+ // ===========================================================================
102
+ // Linear Sync
103
+ // ===========================================================================
104
+ /**
105
+ * Sync a status change to Linear if the ticket has a Linear mapping.
106
+ */
107
+ async syncStatusToLinear(event) {
108
+ if (!isLinearConfigured(this.db))
109
+ return null;
110
+ const config = loadLinearConfig(this.db);
111
+ if (!config)
112
+ return null;
113
+ const mapper = new LinearMapper(this.db);
114
+ const mapping = mapper.getByTicketId(event.ticketId);
115
+ if (!mapping)
116
+ return null;
117
+ // Only sync outbound or bidirectional mappings
118
+ if (mapping.syncDirection === 'inbound')
119
+ return null;
120
+ const category = event.newStatusCategory;
121
+ if (!category) {
122
+ return { provider: 'linear', success: false, error: 'No status category on ticket' };
123
+ }
124
+ try {
125
+ const client = new LinearClient(config.apiKey);
126
+ // Get Linear team's workflow states
127
+ const team = await client.getTeamByKey(mapping.linearTeamKey);
128
+ if (!team) {
129
+ return { provider: 'linear', success: false, error: `Team not found: ${mapping.linearTeamKey}` };
130
+ }
131
+ const states = await client.listStates(team.id);
132
+ const matchingState = states.find((s) => s.type === category);
133
+ if (!matchingState) {
134
+ return { provider: 'linear', success: false, error: `No Linear state for category: ${category}` };
135
+ }
136
+ await client.updateIssueState(mapping.linearIssueId, matchingState.id);
137
+ // Post a comment about the status change
138
+ if (event.newStatusName) {
139
+ await client.addComment(mapping.linearIssueId, `Status updated to **${event.newStatusName}** (via prlt)`);
140
+ }
141
+ mapper.updateSyncTimestamp(event.ticketId);
142
+ return { provider: 'linear', success: true };
143
+ }
144
+ catch (err) {
145
+ return {
146
+ provider: 'linear',
147
+ success: false,
148
+ error: err instanceof Error ? err.message : String(err),
149
+ };
150
+ }
151
+ }
152
+ /**
153
+ * Sync a PR link to Linear if the ticket has a Linear mapping.
154
+ */
155
+ async syncPRToLinear(event) {
156
+ if (!isLinearConfigured(this.db))
157
+ return null;
158
+ const config = loadLinearConfig(this.db);
159
+ if (!config)
160
+ return null;
161
+ const mapper = new LinearMapper(this.db);
162
+ const mapping = mapper.getByTicketId(event.ticketId);
163
+ if (!mapping)
164
+ return null;
165
+ // Only sync outbound or bidirectional mappings
166
+ if (mapping.syncDirection === 'inbound')
167
+ return null;
168
+ try {
169
+ const client = new LinearClient(config.apiKey);
170
+ const sync = new LinearSync(client, mapper);
171
+ const success = await sync.syncPRLink(event.ticketId, event.prUrl, event.prTitle ?? 'Pull Request');
172
+ return { provider: 'linear', success };
173
+ }
174
+ catch (err) {
175
+ return {
176
+ provider: 'linear',
177
+ success: false,
178
+ error: err instanceof Error ? err.message : String(err),
179
+ };
180
+ }
181
+ }
182
+ // ===========================================================================
183
+ // Provider-Agnostic Sync
184
+ // ===========================================================================
185
+ /**
186
+ * Sync status changes to providers tracked via the external_execution_map table.
187
+ * Updates the state snapshot so that future inbound syncs can detect drift.
188
+ */
189
+ async syncStatusToMappedProviders(event) {
190
+ const results = [];
191
+ // Find all external mappings that reference this ticket via execution links
192
+ // or via the latest_state_snapshot containing the ticketId
193
+ const mappings = this.findMappingsForTicket(event.ticketId);
194
+ for (const mapping of mappings) {
195
+ // Skip Linear here (handled separately above with its full API integration)
196
+ if (mapping.provider === 'linear')
197
+ continue;
198
+ try {
199
+ // Update the state snapshot to reflect the new status
200
+ this.mappingStore.upsertMapping({
201
+ provider: mapping.provider,
202
+ externalId: mapping.externalId,
203
+ latestStateSnapshot: {
204
+ ...(mapping.latestStateSnapshot ?? {}),
205
+ ticketStatus: event.newStatusName,
206
+ ticketCategory: event.newStatusCategory,
207
+ lastOutboundSync: new Date().toISOString(),
208
+ },
209
+ lastSyncedAt: new Date(),
210
+ });
211
+ results.push({ provider: mapping.provider, success: true });
212
+ }
213
+ catch (err) {
214
+ results.push({
215
+ provider: mapping.provider,
216
+ success: false,
217
+ error: err instanceof Error ? err.message : String(err),
218
+ });
219
+ }
220
+ }
221
+ return results;
222
+ }
223
+ /**
224
+ * Record a PR URL in all external mappings for a ticket.
225
+ */
226
+ recordPRInMappings(event) {
227
+ const mappings = this.findMappingsForTicket(event.ticketId);
228
+ for (const mapping of mappings) {
229
+ try {
230
+ this.mappingStore.upsertMapping({
231
+ provider: mapping.provider,
232
+ externalId: mapping.externalId,
233
+ prUrl: event.prUrl,
234
+ lastSyncedAt: new Date(),
235
+ });
236
+ }
237
+ catch {
238
+ // Non-fatal
239
+ }
240
+ }
241
+ }
242
+ /**
243
+ * Find external execution mappings associated with a ticket.
244
+ * Checks the latest_state_snapshot for pmoTicketId references.
245
+ */
246
+ findMappingsForTicket(ticketId) {
247
+ // Query external_execution_map where latest_state_snapshot contains the ticketId
248
+ const rows = this.db.prepare(`
249
+ SELECT provider, external_id, latest_state_snapshot
250
+ FROM pmo_external_execution_map
251
+ WHERE latest_state_snapshot LIKE ?
252
+ `).all(`%${ticketId}%`);
253
+ return rows.map((row) => ({
254
+ provider: row.provider,
255
+ externalId: row.external_id,
256
+ latestStateSnapshot: row.latest_state_snapshot ? parseSnapshot(row.latest_state_snapshot) : null,
257
+ }));
258
+ }
259
+ }
260
+ function parseSnapshot(value) {
261
+ try {
262
+ const parsed = JSON.parse(value);
263
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
264
+ return parsed;
265
+ }
266
+ }
267
+ catch {
268
+ // ignore
269
+ }
270
+ return null;
271
+ }
272
+ // =============================================================================
273
+ // Singleton
274
+ // =============================================================================
275
+ let _handler;
276
+ /**
277
+ * Initialize and start the outbound sync handler.
278
+ * Safe to call multiple times — subsequent calls are no-ops.
279
+ */
280
+ export function initOutboundSync(db) {
281
+ if (!_handler) {
282
+ _handler = new OutboundSyncHandler(db);
283
+ _handler.start();
284
+ }
285
+ return _handler;
286
+ }
287
+ /**
288
+ * Stop the outbound sync handler (primarily for testing).
289
+ */
290
+ export function stopOutboundSync() {
291
+ if (_handler) {
292
+ _handler.stop();
293
+ _handler = undefined;
294
+ }
295
+ }
296
+ //# sourceMappingURL=outbound-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-sync.js","sourceRoot":"","sources":["../../../src/lib/external-issues/outbound-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import { type IssueEnvelope, type NormalizedIssueEnvelope } from './types.js';
2
+ export interface TrelloAdapterConfig {
3
+ apiKey?: string;
4
+ apiToken?: string;
5
+ boardId?: string;
6
+ }
7
+ /**
8
+ * Normalize a raw Trello API card into a canonical IssueEnvelope.
9
+ */
10
+ export declare function normalizeTrelloCard(rawCard: unknown, listName?: string): IssueEnvelope;
11
+ /**
12
+ * Normalize a raw Trello card into a PMO-ready NormalizedIssueEnvelope.
13
+ */
14
+ export declare function normalizeTrelloCardToEnvelope(rawCard: unknown, listName?: string): NormalizedIssueEnvelope;
15
+ /**
16
+ * Build a PMO ticket description from a NormalizedIssueEnvelope.
17
+ */
18
+ export declare function buildTrelloTicketDescription(envelope: NormalizedIssueEnvelope): string;
19
+ /**
20
+ * Build ticket metadata from a NormalizedIssueEnvelope for traceability.
21
+ */
22
+ export declare function buildTrelloMetadata(envelope: NormalizedIssueEnvelope): Record<string, string>;
23
+ /**
24
+ * Build a spawn context message from a NormalizedIssueEnvelope.
25
+ */
26
+ export declare function buildTrelloSpawnContextMessage(envelope: NormalizedIssueEnvelope, additionalMessage?: string): string;
27
+ /**
28
+ * Build a CLI command string for selecting a specific Trello card.
29
+ */
30
+ export declare function buildTrelloCardChoiceCommand(cardId: string, projectId?: string): string;
31
+ /**
32
+ * Fetch a single Trello card by its ID and normalize it.
33
+ */
34
+ export declare function getTrelloCardById(configInput: TrelloAdapterConfig, cardId: string, options?: {
35
+ fetchImpl?: typeof fetch;
36
+ }): Promise<NormalizedIssueEnvelope | null>;
37
+ /**
38
+ * Check if Trello is configured via environment variables.
39
+ */
40
+ export declare function isTrelloConfiguredFromEnv(config?: TrelloAdapterConfig): boolean;
41
+ /**
42
+ * Fetch and normalize Trello cards from a board into NormalizedIssueEnvelopes.
43
+ */
44
+ export declare function listTrelloCards(configInput: TrelloAdapterConfig, options?: {
45
+ limit?: number;
46
+ query?: string;
47
+ fetchImpl?: typeof fetch;
48
+ }): Promise<NormalizedIssueEnvelope[]>;
49
+ /**
50
+ * Import a Trello card into PMO as a linked ticket.
51
+ */
52
+ export declare function importTrelloCardToPmo(storage: {
53
+ listTickets(projectId: string): Promise<Array<{
54
+ id: string;
55
+ metadata?: Record<string, string>;
56
+ }>>;
57
+ createTicket(projectId: string, input: {
58
+ title: string;
59
+ description: string;
60
+ priority?: string;
61
+ category?: string;
62
+ labels: string[];
63
+ metadata: Record<string, string>;
64
+ }): Promise<{
65
+ id: string;
66
+ }>;
67
+ updateTicket(ticketId: string, input: {
68
+ title: string;
69
+ description: string;
70
+ priority?: string;
71
+ category?: string;
72
+ labels: string[];
73
+ metadata: Record<string, string>;
74
+ }): Promise<{
75
+ id: string;
76
+ }>;
77
+ }, projectId: string, envelope: NormalizedIssueEnvelope): Promise<{
78
+ ticketId: string;
79
+ created: boolean;
80
+ }>;
@@ -0,0 +1,266 @@
1
+ import { ExternalIssueAdapterError, toNormalizedEnvelope, } from './types.js';
2
+ function ensureTrelloConfig(config) {
3
+ const apiKey = config.apiKey || process.env.PRLT_TRELLO_API_KEY || process.env.TRELLO_API_KEY;
4
+ const apiToken = config.apiToken || process.env.PRLT_TRELLO_API_TOKEN || process.env.TRELLO_API_TOKEN;
5
+ const boardId = config.boardId || process.env.PRLT_TRELLO_BOARD_ID;
6
+ if (!apiKey) {
7
+ throw new ExternalIssueAdapterError('MISSING_CONFIG', 'Missing Trello API key. Set TRELLO_API_KEY or PRLT_TRELLO_API_KEY, or run "prlt trello configure".');
8
+ }
9
+ if (!apiToken) {
10
+ throw new ExternalIssueAdapterError('MISSING_CONFIG', 'Missing Trello API token. Set TRELLO_API_TOKEN or PRLT_TRELLO_API_TOKEN, or run "prlt trello configure".');
11
+ }
12
+ return { apiKey, apiToken, boardId: boardId || undefined };
13
+ }
14
+ function ensureCardShape(card) {
15
+ if (!card.id || !card.name || !card.url) {
16
+ throw new ExternalIssueAdapterError('BAD_PAYLOAD', 'Trello card payload is missing required fields (id, name, url).', card);
17
+ }
18
+ }
19
+ function deriveTrelloLabels(card) {
20
+ if (!Array.isArray(card.labels)) {
21
+ return [];
22
+ }
23
+ return card.labels
24
+ .map(label => label.name?.trim())
25
+ .filter((name) => Boolean(name));
26
+ }
27
+ function deriveTrelloPriority(labels) {
28
+ const priorityLabel = labels.find(l => /^P[0-3]$/i.test(l));
29
+ return priorityLabel ? priorityLabel.toUpperCase() : null;
30
+ }
31
+ function deriveTrelloAssignee(card) {
32
+ const members = card.members;
33
+ if (Array.isArray(members) && members.length > 0) {
34
+ return members[0]?.fullName || members[0]?.username || null;
35
+ }
36
+ return null;
37
+ }
38
+ function deriveCategory(_card) {
39
+ return 'feature';
40
+ }
41
+ /**
42
+ * Normalize a raw Trello API card into a canonical IssueEnvelope.
43
+ */
44
+ export function normalizeTrelloCard(rawCard, listName) {
45
+ if (!rawCard || typeof rawCard !== 'object') {
46
+ throw new ExternalIssueAdapterError('BAD_PAYLOAD', 'Trello card payload is invalid.', rawCard);
47
+ }
48
+ const card = rawCard;
49
+ ensureCardShape(card);
50
+ const labels = deriveTrelloLabels(card);
51
+ return {
52
+ source: 'trello',
53
+ external_id: card.id,
54
+ external_key: card.id,
55
+ title: card.name,
56
+ description: card.desc || '',
57
+ labels,
58
+ priority: deriveTrelloPriority(labels),
59
+ status: listName ?? (card.closed ? 'Closed' : 'Open'),
60
+ url: card.url,
61
+ project_key: card.idBoard || 'DEFAULT',
62
+ assignee: deriveTrelloAssignee(card),
63
+ item_type: 'card',
64
+ raw: rawCard,
65
+ };
66
+ }
67
+ /**
68
+ * Normalize a raw Trello card into a PMO-ready NormalizedIssueEnvelope.
69
+ */
70
+ export function normalizeTrelloCardToEnvelope(rawCard, listName) {
71
+ const envelope = normalizeTrelloCard(rawCard, listName);
72
+ const card = rawCard;
73
+ return toNormalizedEnvelope(envelope, deriveCategory(card));
74
+ }
75
+ /**
76
+ * Build a PMO ticket description from a NormalizedIssueEnvelope.
77
+ */
78
+ export function buildTrelloTicketDescription(envelope) {
79
+ const body = envelope.description.trim();
80
+ const metadataLines = [
81
+ `- Source: ${envelope.source.name}`,
82
+ `- External key: ${envelope.source.externalKey}`,
83
+ `- External id: ${envelope.source.externalId}`,
84
+ `- URL: ${envelope.source.url}`,
85
+ `- Status: ${envelope.status}`,
86
+ `- Priority: ${envelope.priority || 'Unset'}`,
87
+ `- Labels: ${envelope.labels.length > 0 ? envelope.labels.join(', ') : 'None'}`,
88
+ ];
89
+ const parts = [
90
+ body,
91
+ '## External Issue Context',
92
+ metadataLines.join('\n'),
93
+ ].filter(Boolean);
94
+ return parts.join('\n\n');
95
+ }
96
+ /**
97
+ * Build ticket metadata from a NormalizedIssueEnvelope for traceability.
98
+ */
99
+ export function buildTrelloMetadata(envelope) {
100
+ return {
101
+ external_source: envelope.source.name,
102
+ external_key: envelope.source.externalKey,
103
+ external_id: envelope.source.externalId,
104
+ external_url: envelope.source.url,
105
+ external_raw: JSON.stringify(envelope.source.raw),
106
+ };
107
+ }
108
+ /**
109
+ * Build a spawn context message from a NormalizedIssueEnvelope.
110
+ */
111
+ export function buildTrelloSpawnContextMessage(envelope, additionalMessage) {
112
+ const lines = [
113
+ `External issue source: ${envelope.source.name}`,
114
+ `External issue key: ${envelope.source.externalKey}`,
115
+ `External issue id: ${envelope.source.externalId}`,
116
+ `External issue URL: ${envelope.source.url}`,
117
+ ];
118
+ if (additionalMessage?.trim()) {
119
+ lines.push('', additionalMessage.trim());
120
+ }
121
+ return lines.join('\n');
122
+ }
123
+ /**
124
+ * Build a CLI command string for selecting a specific Trello card.
125
+ */
126
+ export function buildTrelloCardChoiceCommand(cardId, projectId) {
127
+ let command = `prlt work start --from trello:${cardId} --json`;
128
+ if (projectId) {
129
+ command += ` -P ${projectId}`;
130
+ }
131
+ return command;
132
+ }
133
+ /**
134
+ * Fetch the list name for a card's idList.
135
+ */
136
+ async function fetchListName(config, listId, options) {
137
+ const fetchImpl = options?.fetchImpl || fetch;
138
+ try {
139
+ const url = `https://api.trello.com/1/lists/${listId}?key=${encodeURIComponent(config.apiKey)}&token=${encodeURIComponent(config.apiToken)}&fields=name`;
140
+ const response = await fetchImpl(url);
141
+ if (!response.ok)
142
+ return undefined;
143
+ const list = await response.json();
144
+ return list.name ?? undefined;
145
+ }
146
+ catch {
147
+ return undefined;
148
+ }
149
+ }
150
+ /**
151
+ * Fetch a single Trello card by its ID and normalize it.
152
+ */
153
+ export async function getTrelloCardById(configInput, cardId, options) {
154
+ const config = ensureTrelloConfig(configInput);
155
+ const fetchImpl = options?.fetchImpl || fetch;
156
+ const url = `https://api.trello.com/1/cards/${encodeURIComponent(cardId)}?key=${encodeURIComponent(config.apiKey)}&token=${encodeURIComponent(config.apiToken)}&fields=id,name,desc,url,shortUrl,idBoard,idList,idMembers,closed,due,dueComplete&members=true&member_fields=fullName,username&labels=all`;
157
+ const response = await fetchImpl(url);
158
+ if (response.status === 401 || response.status === 403) {
159
+ throw new ExternalIssueAdapterError('AUTH_FAILED', 'Trello authentication failed. Verify your API key and token.');
160
+ }
161
+ if (response.status === 429) {
162
+ throw new ExternalIssueAdapterError('RATE_LIMITED', 'Trello API rate limit exceeded. Wait a moment and try again.');
163
+ }
164
+ if (response.status === 404) {
165
+ return null;
166
+ }
167
+ if (!response.ok) {
168
+ throw new ExternalIssueAdapterError('REQUEST_FAILED', `Trello request failed with status ${response.status}.`);
169
+ }
170
+ const payload = await response.json();
171
+ // Resolve list name for status
172
+ const listName = payload.idList
173
+ ? await fetchListName(config, payload.idList, { fetchImpl })
174
+ : undefined;
175
+ return normalizeTrelloCardToEnvelope(payload, listName);
176
+ }
177
+ /**
178
+ * Check if Trello is configured via environment variables.
179
+ */
180
+ export function isTrelloConfiguredFromEnv(config) {
181
+ const apiKey = config?.apiKey
182
+ || process.env.PRLT_TRELLO_API_KEY
183
+ || process.env.TRELLO_API_KEY;
184
+ const apiToken = config?.apiToken
185
+ || process.env.PRLT_TRELLO_API_TOKEN
186
+ || process.env.TRELLO_API_TOKEN;
187
+ return Boolean(apiKey && apiToken);
188
+ }
189
+ /**
190
+ * Fetch and normalize Trello cards from a board into NormalizedIssueEnvelopes.
191
+ */
192
+ export async function listTrelloCards(configInput, options) {
193
+ const config = ensureTrelloConfig(configInput);
194
+ const fetchImpl = options?.fetchImpl || fetch;
195
+ const limit = Math.max(1, Math.min(options?.limit ?? 20, 100));
196
+ if (!config.boardId && !options?.query) {
197
+ throw new ExternalIssueAdapterError('MISSING_CONFIG', 'Missing Trello board ID. Run "prlt trello configure" and select a board, or set PRLT_TRELLO_BOARD_ID.');
198
+ }
199
+ // If query, use search endpoint
200
+ if (options?.query) {
201
+ const url = `https://api.trello.com/1/search?key=${encodeURIComponent(config.apiKey)}&token=${encodeURIComponent(config.apiToken)}&query=${encodeURIComponent(options.query)}&modelTypes=cards&cards_limit=${limit}&card_fields=id,name,desc,url,shortUrl,idBoard,idList,idMembers,closed,due,dueComplete&card_members=true&card_member_fields=fullName,username&card_labels=all`;
202
+ const response = await fetchImpl(url);
203
+ if (response.status === 401 || response.status === 403) {
204
+ throw new ExternalIssueAdapterError('AUTH_FAILED', 'Trello authentication failed. Verify your API key and token.');
205
+ }
206
+ if (!response.ok) {
207
+ throw new ExternalIssueAdapterError('REQUEST_FAILED', `Trello request failed with status ${response.status}.`);
208
+ }
209
+ const payload = await response.json();
210
+ const cards = payload.cards ?? [];
211
+ return cards.slice(0, limit).map(card => normalizeTrelloCardToEnvelope(card));
212
+ }
213
+ // Otherwise, list from board
214
+ const url = `https://api.trello.com/1/boards/${encodeURIComponent(config.boardId)}/cards/open?key=${encodeURIComponent(config.apiKey)}&token=${encodeURIComponent(config.apiToken)}&fields=id,name,desc,url,shortUrl,idBoard,idList,idMembers,closed,due,dueComplete&members=true&member_fields=fullName,username&labels=all`;
215
+ const response = await fetchImpl(url);
216
+ if (response.status === 401 || response.status === 403) {
217
+ throw new ExternalIssueAdapterError('AUTH_FAILED', 'Trello authentication failed. Verify your API key and token.');
218
+ }
219
+ if (!response.ok) {
220
+ throw new ExternalIssueAdapterError('REQUEST_FAILED', `Trello request failed with status ${response.status}.`);
221
+ }
222
+ const cards = await response.json();
223
+ if (!Array.isArray(cards)) {
224
+ throw new ExternalIssueAdapterError('BAD_PAYLOAD', 'Trello response payload was missing cards array.', cards);
225
+ }
226
+ return cards.slice(0, limit).map(card => normalizeTrelloCardToEnvelope(card));
227
+ }
228
+ /**
229
+ * Import a Trello card into PMO as a linked ticket.
230
+ */
231
+ export async function importTrelloCardToPmo(storage, projectId, envelope) {
232
+ const tickets = await storage.listTickets(projectId);
233
+ const existing = tickets.find((ticket) => {
234
+ const source = ticket.metadata?.external_source;
235
+ const key = ticket.metadata?.external_key;
236
+ const id = ticket.metadata?.external_id;
237
+ return source === 'trello'
238
+ && (key === envelope.source.externalKey || id === envelope.source.externalId);
239
+ });
240
+ const description = buildTrelloTicketDescription(envelope);
241
+ const metadata = buildTrelloMetadata(envelope);
242
+ if (existing) {
243
+ await storage.updateTicket(existing.id, {
244
+ title: envelope.title,
245
+ description,
246
+ priority: envelope.priority ?? undefined,
247
+ category: envelope.category ?? undefined,
248
+ labels: envelope.labels,
249
+ metadata: {
250
+ ...existing.metadata,
251
+ ...metadata,
252
+ },
253
+ });
254
+ return { ticketId: existing.id, created: false };
255
+ }
256
+ const ticket = await storage.createTicket(projectId, {
257
+ title: envelope.title,
258
+ description,
259
+ priority: envelope.priority ?? undefined,
260
+ category: envelope.category ?? undefined,
261
+ labels: envelope.labels,
262
+ metadata,
263
+ });
264
+ return { ticketId: ticket.id, created: true };
265
+ }
266
+ //# sourceMappingURL=trello.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trello.js","sourceRoot":"","sources":["../../../src/lib/external-issues/trello.ts"],"names":[],"mappings":"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"}