@temporal-architect/claude-plugin 0.9.0

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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/package.json +37 -0
  4. package/skills/MANIFEST.json +373 -0
  5. package/skills/MANIFEST.md +121 -0
  6. package/skills/temporal-architect/SKILL.md +99 -0
  7. package/skills/temporal-architect/reference/decomposition.md +78 -0
  8. package/skills/temporal-architect-author-go/README.md +16 -0
  9. package/skills/temporal-architect-author-go/SKILL.md +191 -0
  10. package/skills/temporal-architect-author-go/SUBAGENT_ADOPTION.md +161 -0
  11. package/skills/temporal-architect-author-go/reference/activity-call.md +73 -0
  12. package/skills/temporal-architect-author-go/reference/activity-def.md +54 -0
  13. package/skills/temporal-architect-author-go/reference/assignment.md +36 -0
  14. package/skills/temporal-architect-author-go/reference/await-all.md +104 -0
  15. package/skills/temporal-architect-author-go/reference/await-one.md +193 -0
  16. package/skills/temporal-architect-author-go/reference/await-timer.md +35 -0
  17. package/skills/temporal-architect-author-go/reference/close.md +71 -0
  18. package/skills/temporal-architect-author-go/reference/composite-patterns.md +176 -0
  19. package/skills/temporal-architect-author-go/reference/condition.md +56 -0
  20. package/skills/temporal-architect-author-go/reference/control-flow.md +151 -0
  21. package/skills/temporal-architect-author-go/reference/dependency-resolution.md +29 -0
  22. package/skills/temporal-architect-author-go/reference/detach.md +52 -0
  23. package/skills/temporal-architect-author-go/reference/heartbeat.md +84 -0
  24. package/skills/temporal-architect-author-go/reference/nexus-service-def.md +73 -0
  25. package/skills/temporal-architect-author-go/reference/nexus.md +35 -0
  26. package/skills/temporal-architect-author-go/reference/options.md +138 -0
  27. package/skills/temporal-architect-author-go/reference/promise.md +73 -0
  28. package/skills/temporal-architect-author-go/reference/proto-driven.md +197 -0
  29. package/skills/temporal-architect-author-go/reference/query-handler.md +34 -0
  30. package/skills/temporal-architect-author-go/reference/signal-handler.md +73 -0
  31. package/skills/temporal-architect-author-go/reference/three-layer-testing.md +173 -0
  32. package/skills/temporal-architect-author-go/reference/types.md +72 -0
  33. package/skills/temporal-architect-author-go/reference/update-handler.md +64 -0
  34. package/skills/temporal-architect-author-go/reference/worker.md +215 -0
  35. package/skills/temporal-architect-author-go/reference/workflow-call.md +37 -0
  36. package/skills/temporal-architect-author-go/reference/workflow-def.md +45 -0
  37. package/skills/temporal-architect-author-infra/README.md +16 -0
  38. package/skills/temporal-architect-author-infra/SKILL.md +132 -0
  39. package/skills/temporal-architect-author-infra/reference/tcld.md +112 -0
  40. package/skills/temporal-architect-author-infra/reference/terraform.md +125 -0
  41. package/skills/temporal-architect-design/README.md +16 -0
  42. package/skills/temporal-architect-design/SKILL.md +224 -0
  43. package/skills/temporal-architect-design/reference/LANGUAGE.md +5 -0
  44. package/skills/temporal-architect-design/reference/anti-patterns.md +332 -0
  45. package/skills/temporal-architect-design/reference/common-errors.md +88 -0
  46. package/skills/temporal-architect-design/reference/core-principles.md +52 -0
  47. package/skills/temporal-architect-design/reference/design-checklist.md +59 -0
  48. package/skills/temporal-architect-design/reference/namespaces.md +84 -0
  49. package/skills/temporal-architect-design/reference/notation-examples.md +304 -0
  50. package/skills/temporal-architect-design/reference/notation-reference.md +70 -0
  51. package/skills/temporal-architect-design/reference/primitives-reference.md +65 -0
  52. package/skills/temporal-architect-design/reference/project-discovery-subagent.md +80 -0
  53. package/skills/temporal-architect-design/reference/reverse-engineering.md +53 -0
  54. package/skills/temporal-architect-design/reference/twf-conventions.md +43 -0
  55. package/skills/temporal-architect-design/reference/workflow-boundaries.md +43 -0
  56. package/skills/temporal-architect-design/topics/activities-advanced.md +358 -0
  57. package/skills/temporal-architect-design/topics/activities-advanced.twf +107 -0
  58. package/skills/temporal-architect-design/topics/child-workflows.md +347 -0
  59. package/skills/temporal-architect-design/topics/child-workflows.twf +171 -0
  60. package/skills/temporal-architect-design/topics/long-running.md +230 -0
  61. package/skills/temporal-architect-design/topics/long-running.twf +100 -0
  62. package/skills/temporal-architect-design/topics/nexus.md +248 -0
  63. package/skills/temporal-architect-design/topics/nexus.twf +148 -0
  64. package/skills/temporal-architect-design/topics/patterns.md +469 -0
  65. package/skills/temporal-architect-design/topics/patterns.twf +346 -0
  66. package/skills/temporal-architect-design/topics/promises-conditions.md +179 -0
  67. package/skills/temporal-architect-design/topics/promises-conditions.twf +213 -0
  68. package/skills/temporal-architect-design/topics/signals-queries-updates.md +319 -0
  69. package/skills/temporal-architect-design/topics/signals-queries-updates.twf +234 -0
  70. package/skills/temporal-architect-design/topics/task-queues.md +205 -0
  71. package/skills/temporal-architect-design/topics/task-queues.twf +184 -0
  72. package/skills/temporal-architect-design/topics/testing.md +437 -0
  73. package/skills/temporal-architect-design/topics/testing.twf +177 -0
  74. package/skills/temporal-architect-design/topics/timers-scheduling.md +131 -0
  75. package/skills/temporal-architect-design/topics/timers-scheduling.twf +129 -0
  76. package/skills/temporal-architect-design/topics/versioning.md +434 -0
  77. package/skills/temporal-architect-design/topics/versioning.twf +174 -0
@@ -0,0 +1,346 @@
1
+ # Source: patterns.md
2
+ # Patterns: process, entity, saga, fan-out/fan-in, pipeline, state machine, polling
3
+
4
+ # --- Process Workflow ---
5
+
6
+ workflow OrderFulfillment(order: Order) -> (OrderResult):
7
+ # Step 1: Validate
8
+ activity ValidateRetailOrder(order) -> validated
9
+ if (validated.success == false):
10
+ close fail(OrderResult{status: "invalid", error: validated.error})
11
+
12
+ # Step 2: Reserve
13
+ activity ReserveInventory(order.items) -> reservation
14
+
15
+ # Step 3: Charge
16
+ activity ProcessPayment(order.payment) -> payment
17
+
18
+ # Step 4: Fulfill
19
+ activity ShipRetailOrder(order, reservation)
20
+
21
+ # Step 5: Notify
22
+ activity SendConfirmation(order.customer)
23
+
24
+ close complete(OrderResult{status: "completed", trackingId: reservation.trackingId})
25
+
26
+ # --- Entity Workflow ---
27
+
28
+ workflow AccountEntity(accountId: string, account: Account):
29
+ signal Deposit(amount: decimal):
30
+ account.balance = account.balance + amount
31
+
32
+ signal Withdraw(amount: decimal):
33
+ if (account.balance >= amount):
34
+ account.balance = account.balance - amount
35
+
36
+ signal Close():
37
+ closePending = true
38
+
39
+ query GetBalance() -> (decimal):
40
+ return account.balance
41
+
42
+ update Transfer(amount: decimal, toAccount: string) -> (TransferResult):
43
+ if (account.balance < amount):
44
+ return TransferResult{success: false, error: "insufficient funds"}
45
+ account.balance = account.balance - amount
46
+ activity RecordAccountTransaction(accountId, "transfer")
47
+ return TransferResult{success: true}
48
+
49
+ if (account == null):
50
+ activity LoadAccount(accountId) -> account
51
+
52
+ eventCount = 0
53
+ closePending = false
54
+
55
+ for:
56
+ await one:
57
+ signal Deposit:
58
+ activity RecordAccountTransaction(accountId, "deposit")
59
+ signal Withdraw:
60
+ activity RecordAccountTransaction(accountId, "withdraw")
61
+ signal Close:
62
+ activity CloseAccount(accountId)
63
+ close complete
64
+ timer(24h):
65
+ activity DailyReconciliation(accountId)
66
+
67
+ eventCount = eventCount + 1
68
+ if (eventCount > 1000):
69
+ close continue_as_new(accountId, account)
70
+
71
+ # --- Saga Pattern (adapted without try/catch) ---
72
+
73
+ workflow BookingWorkflow(booking: Booking) -> (BookingResult):
74
+ # Step 1: Reserve flight
75
+ activity ReserveFlight(booking.flight) -> flight
76
+
77
+ # Step 2: Reserve hotel (compensate flight if this fails)
78
+ activity ReserveHotel(booking.hotel) -> hotel
79
+ if (hotel.failed):
80
+ activity CancelFlight(flight.id)
81
+ close fail(BookingResult{status: "hotel_failed"})
82
+
83
+ # Step 3: Reserve car (compensate flight + hotel if this fails)
84
+ activity ReserveCar(booking.car) -> car
85
+ if (car.failed):
86
+ activity CancelFlight(flight.id)
87
+ activity CancelHotel(hotel.id)
88
+ close fail(BookingResult{status: "car_failed"})
89
+
90
+ # Step 4: Charge payment (compensate all if this fails)
91
+ activity ChargeBookingPayment(booking.payment) -> payment
92
+ if (payment.failed):
93
+ workflow CompensateBooking(flight.id, hotel.id, car.id)
94
+ close fail(BookingResult{status: "payment_failed"})
95
+
96
+ # All succeeded
97
+ close complete(BookingResult{status: "confirmed"})
98
+
99
+ # --- Saga compensation workflow (called on failure) ---
100
+
101
+ workflow CompensateBooking(flight: string, hotel: string, car: string):
102
+ # Run compensations
103
+ activity CancelFlight(flight)
104
+ activity CancelHotel(hotel)
105
+ activity CancelCar(car)
106
+ close complete
107
+
108
+ # --- Fan-Out/Fan-In ---
109
+
110
+ workflow BatchProcessor(items: []Item) -> (BatchResult):
111
+ # Fan-out: start all processing in parallel
112
+ await all:
113
+ for (item in items):
114
+ activity ProcessBatchItem(item)
115
+
116
+ # Fan-in: aggregate results (SDK collects results from await all)
117
+ activity AggregateResults(items) -> aggregated
118
+ close complete(BatchResult{processed: aggregated.count})
119
+
120
+ # --- Pipeline ---
121
+
122
+ workflow DataPipeline(rawData: RawData) -> (ProcessedData):
123
+ # Stage 1: Ingest
124
+ activity Ingest(rawData) -> ingested
125
+
126
+ # Stage 2: Validate
127
+ activity Validate(ingested) -> validated
128
+ if (validated.valid == false):
129
+ close fail(ProcessedData{status: "invalid", errors: validated.errors})
130
+
131
+ # Stage 3: Transform
132
+ activity Transform(validated.data) -> transformed
133
+
134
+ # Stage 4: Enrich
135
+ activity Enrich(transformed) -> enriched
136
+
137
+ # Stage 5: Load
138
+ activity Load(enriched)
139
+
140
+ close complete(ProcessedData{status: "complete", recordCount: enriched.count})
141
+
142
+ # --- State Machine ---
143
+
144
+ workflow DocumentApproval(doc: Document) -> (ApprovalResult):
145
+ signal Submit():
146
+ phase = "pending_review"
147
+ activity NotifyReviewers(doc)
148
+
149
+ signal Approve():
150
+ phase = "approved"
151
+
152
+ signal Reject():
153
+ phase = "rejected"
154
+
155
+ signal RequestChanges():
156
+ phase = "changes_requested"
157
+
158
+ signal Withdraw():
159
+ phase = "withdrawn"
160
+
161
+ phase = "draft"
162
+
163
+ for:
164
+ switch (phase):
165
+ case "draft":
166
+ await one:
167
+ signal Submit:
168
+ timer(90d):
169
+ phase = "expired"
170
+ case "pending_review":
171
+ await one:
172
+ signal Approve:
173
+ signal Reject:
174
+ signal RequestChanges:
175
+ timer(30d):
176
+ phase = "expired"
177
+ case "changes_requested":
178
+ await one:
179
+ signal Submit:
180
+ signal Withdraw:
181
+ timer(30d):
182
+ phase = "expired"
183
+ case "approved":
184
+ activity PublishDocument(doc)
185
+ close complete(ApprovalResult{status: "approved"})
186
+ case "rejected":
187
+ activity ArchiveDocument(doc)
188
+ close complete(ApprovalResult{status: "rejected"})
189
+ case "withdrawn":
190
+ close complete(ApprovalResult{status: "withdrawn"})
191
+ case "expired":
192
+ close complete(ApprovalResult{status: "expired"})
193
+
194
+ # --- Polling ---
195
+
196
+ workflow AwaitResourceReady(resourceId: string) -> (Resource):
197
+ backoff = 5s
198
+ maxBackoff = 60s
199
+
200
+ for:
201
+ activity CheckResourceStatus(resourceId) -> status
202
+
203
+ if (status.ready):
204
+ activity GetResource(resourceId) -> resource
205
+ close complete(resource)
206
+
207
+ if (status.failed):
208
+ close fail(Resource{error: status.error})
209
+
210
+ # Wait with backoff, timeout via await one + timer
211
+ await one:
212
+ timer(backoff):
213
+ backoff = min(backoff * 2, maxBackoff)
214
+ timer(30m):
215
+ close fail(Resource{error: "timeout"})
216
+
217
+ # --- Supporting activities ---
218
+
219
+ activity ValidateRetailOrder(order: Order) -> (ValidateResult):
220
+ return validate(order)
221
+
222
+ activity ReserveInventory(items: []Item) -> (Reservation):
223
+ return reserve(items)
224
+
225
+ activity ProcessPayment(payment: Payment) -> (PaymentResult):
226
+ return charge(payment)
227
+
228
+ activity ShipRetailOrder(order: Order, reservation: Reservation):
229
+ ship(order, reservation)
230
+
231
+ activity SendConfirmation(customer: Customer):
232
+ notify(customer)
233
+
234
+ activity LoadAccount(accountId: string) -> (Account):
235
+ return db.load(accountId)
236
+
237
+ activity RecordAccountTransaction(accountId: string, txType: string):
238
+ db.record(accountId, txType)
239
+
240
+ activity CloseAccount(accountId: string):
241
+ db.close(accountId)
242
+
243
+ activity DailyReconciliation(accountId: string):
244
+ reconcile(accountId)
245
+
246
+ activity ReserveFlight(flight: FlightSpec) -> (FlightReservation):
247
+ return reserve(flight)
248
+
249
+ activity ReserveHotel(hotel: HotelSpec) -> (HotelReservation):
250
+ return reserve(hotel)
251
+
252
+ activity ReserveCar(car: CarSpec) -> (CarReservation):
253
+ return reserve(car)
254
+
255
+ activity ChargeBookingPayment(payment: Payment) -> (PaymentResult):
256
+ return charge(payment)
257
+
258
+ activity CancelFlight(flightId: string):
259
+ cancel(flightId)
260
+
261
+ activity CancelHotel(hotelId: string):
262
+ cancel(hotelId)
263
+
264
+ activity CancelCar(carId: string):
265
+ cancel(carId)
266
+
267
+ activity ProcessBatchItem(item: Item) -> (ItemResult):
268
+ return process(item)
269
+
270
+ activity AggregateResults(results: []ItemResult) -> (AggregateResult):
271
+ return aggregate(results)
272
+
273
+ activity Ingest(rawData: RawData) -> (IngestedData):
274
+ return ingest(rawData)
275
+
276
+ activity Validate(data: IngestedData) -> (ValidationResult):
277
+ return validate(data)
278
+
279
+ activity Transform(data: ValidatedData) -> (TransformedData):
280
+ return transform(data)
281
+
282
+ activity Enrich(data: TransformedData) -> (EnrichedData):
283
+ return enrich(data)
284
+
285
+ activity Load(data: EnrichedData):
286
+ load(data)
287
+
288
+ activity NotifyReviewers(doc: Document):
289
+ notify(doc.reviewers)
290
+
291
+ activity PublishDocument(doc: Document):
292
+ publish(doc)
293
+
294
+ activity ArchiveDocument(doc: Document):
295
+ archive(doc)
296
+
297
+ activity CheckResourceStatus(resourceId: string) -> (ResourceStatus):
298
+ return check(resourceId)
299
+
300
+ activity GetResource(resourceId: string) -> (Resource):
301
+ return fetch(resourceId)
302
+
303
+ # --- Worker and namespace ---
304
+
305
+ worker patternsWorker:
306
+ workflow OrderFulfillment
307
+ workflow AccountEntity
308
+ workflow BookingWorkflow
309
+ workflow CompensateBooking
310
+ workflow BatchProcessor
311
+ workflow DataPipeline
312
+ workflow DocumentApproval
313
+ workflow AwaitResourceReady
314
+ activity ValidateRetailOrder
315
+ activity ReserveInventory
316
+ activity ProcessPayment
317
+ activity ShipRetailOrder
318
+ activity SendConfirmation
319
+ activity LoadAccount
320
+ activity RecordAccountTransaction
321
+ activity CloseAccount
322
+ activity DailyReconciliation
323
+ activity ReserveFlight
324
+ activity ReserveHotel
325
+ activity ReserveCar
326
+ activity ChargeBookingPayment
327
+ activity CancelFlight
328
+ activity CancelHotel
329
+ activity CancelCar
330
+ activity ProcessBatchItem
331
+ activity AggregateResults
332
+ activity Ingest
333
+ activity Validate
334
+ activity Transform
335
+ activity Enrich
336
+ activity Load
337
+ activity NotifyReviewers
338
+ activity PublishDocument
339
+ activity ArchiveDocument
340
+ activity CheckResourceStatus
341
+ activity GetResource
342
+
343
+ namespace patterns:
344
+ worker patternsWorker
345
+ options:
346
+ task_queue: "patterns"
@@ -0,0 +1,179 @@
1
+ # Promises and Conditions
2
+
3
+ > **Example:** [`promises-conditions.twf`](./promises-conditions.twf)
4
+
5
+ Deferred async operations and named boolean awaitables for workflow state.
6
+
7
+ ## Overview
8
+
9
+ | Primitive | Purpose | Syntax |
10
+ |-----------|---------|--------|
11
+ | **Promise** | Start async operation, await later | `promise p <- activity Foo(x)` |
12
+ | **Condition** | Named boolean awaitable | `condition myCondition` (in `state:` block) |
13
+ | **Set / Unset** | Mutate a condition | `set myCondition` / `unset myCondition` |
14
+ | **State block** | Declare workflow state | `state:` (before handlers) |
15
+
16
+ ---
17
+
18
+ ## Promises
19
+
20
+ A `promise` wraps any async operation (activity, workflow, timer, signal, update) for non-blocking execution. The `<-` operator visually distinguishes async declaration from sync result binding (`->`).
21
+
22
+ ### Declaration
23
+
24
+ ```twf
25
+ promise p <- activity ProcessItem(input)
26
+ promise report <- workflow BuildReport(data)
27
+ promise timeout <- timer(5m)
28
+ promise approved <- signal Approved
29
+ promise addr <- update ChangeAddress
30
+ promise pay <- nexus BillingEndpoint BillingService.ChargePayment(card)
31
+ ```
32
+
33
+ ### Awaiting a Promise
34
+
35
+ Block until the promise resolves and bind the result:
36
+
37
+ ```twf
38
+ await p -> result
39
+ await timeout
40
+ ```
41
+
42
+ ### Promises in `await one` (race)
43
+
44
+ ```twf
45
+ await one:
46
+ p -> result:
47
+ close complete(Result{data: result})
48
+ timeout:
49
+ close fail("timed out")
50
+ ```
51
+
52
+ > **The promise's operation is not cancelled when it loses.** If `timeout` wins, the operation backing `p` (the activity/workflow/nexus call started by `promise p <- ...`) keeps running until the workflow run ends — racing a promise against a timeout does **not** cancel the promise. If the losing operation must actually stop, add explicit cleanup; the race alone won't release it.
53
+
54
+ ### Start-Now, Wait-Later Pattern
55
+
56
+ The primary use case for promises is starting operations without blocking, doing other work, then collecting results:
57
+
58
+ ```twf
59
+ workflow ParallelProcessing(items: Items) -> (Result):
60
+ promise handleA <- activity ProcessA(items.a)
61
+ promise handleB <- activity ProcessB(items.b)
62
+
63
+ activity QuickSetup(items)
64
+
65
+ await handleA -> resultA
66
+ await handleB -> resultB
67
+
68
+ close complete(Result{a: resultA, b: resultB})
69
+ ```
70
+
71
+ ### Async Duality
72
+
73
+ Every async operation has two forms:
74
+
75
+ | Form | Syntax | Behavior |
76
+ |------|--------|----------|
77
+ | **Blocking** | `activity Process(item) -> result` | Start and wait immediately |
78
+ | **Non-blocking** | `promise p <- activity Process(item)` | Start, continue, wait later |
79
+
80
+ This applies uniformly to: `activity`, `workflow`, `timer`, `signal`, `update`.
81
+
82
+ ---
83
+
84
+ ## Conditions
85
+
86
+ A `condition` is a named boolean temporal primitive declared in the workflow `state:` block. It can be set, unset, and awaited.
87
+
88
+ ### Declaration (in `state:` block only)
89
+
90
+ ```twf
91
+ workflow Example():
92
+ state:
93
+ condition clusterStarted
94
+ condition thresholdReached
95
+ ```
96
+
97
+ ### Mutation
98
+
99
+ ```twf
100
+ set clusterStarted
101
+ unset clusterStarted
102
+ ```
103
+
104
+ ### Awaiting a Condition
105
+
106
+ ```twf
107
+ await clusterStarted
108
+ ```
109
+
110
+ ### Conditions in `await one` (race)
111
+
112
+ ```twf
113
+ await one:
114
+ clusterStarted:
115
+ close complete(ClusterState{started: true})
116
+ timer(30d):
117
+ close fail("timeout")
118
+ ```
119
+
120
+ ### Update Handler + Condition Pattern
121
+
122
+ The primary motivator for conditions: update handlers that wait on workflow state. The client blocks until the handler returns, and the handler waits for a condition that the main workflow body sets:
123
+
124
+ ```twf
125
+ workflow ClusterManager(config: Config):
126
+ state:
127
+ condition clusterStarted
128
+
129
+ update WaitUntilStarted() -> (ClusterState):
130
+ await clusterStarted
131
+ return ClusterState{started: true}
132
+
133
+ activity ProvisionCluster(config)
134
+ activity StartCluster(config)
135
+ set clusterStarted
136
+
137
+ await signal Shutdown
138
+ close complete
139
+ ```
140
+
141
+ ---
142
+
143
+ ## State Block
144
+
145
+ The `state:` block declares workflow state including conditions and variable initializations. It must appear first in a workflow definition, before signal/query/update handlers.
146
+
147
+ ```twf
148
+ workflow Example():
149
+ state:
150
+ condition myCondition
151
+ balance = 0
152
+ status = "pending"
153
+
154
+ signal Deposit(amount: decimal):
155
+ balance = balance + amount
156
+ if (balance >= 1000):
157
+ set myCondition
158
+
159
+ await myCondition
160
+ close complete
161
+ ```
162
+
163
+ ### Restrictions
164
+
165
+ - No temporal primitives inside `state:` block (it is purely declarative)
166
+ - `condition` declarations can only appear inside `state:` blocks
167
+ - `set`/`unset` targets must refer to conditions declared in the `state:` block
168
+
169
+ ---
170
+
171
+ ## Condition Considerations
172
+
173
+ | Consideration | Guidance |
174
+ |---------------|----------|
175
+ | **Boolean only** | Conditions are simple true/false values |
176
+ | **Declarative** | Must be declared in `state:` block before use |
177
+ | **Signal-driven** | Typically set/unset in signal or update handlers |
178
+ | **Reactive** | `await condition` unblocks when condition becomes true |
179
+ | **No expressions** | Conditions are named booleans, not arbitrary predicates |