@rubytech/taskmaster 1.27.0 → 1.28.1

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.
@@ -17,6 +17,11 @@ Before doing anything else:
17
17
  - sessionTarget: `isolated`, wakeMode: `next-heartbeat`
18
18
  - message: `Run the ride booking stall check.`
19
19
  - deliver: false (operator does not need a notification unless a stall is found)
20
+ 5. Ensure the booking lifecycle cron job is configured — call `cron` with action: `list` and check for a job named "Booking Lifecycle Check". If it does not exist, create it:
21
+ - action: `add`, name: `Booking Lifecycle Check`, schedule: `*/10 * * * *` (every 10 minutes)
22
+ - sessionTarget: `isolated`, wakeMode: `next-heartbeat`
23
+ - message: `Run the booking lifecycle check.`
24
+ - deliver: false
20
25
 
21
26
  ## Tools
22
27
 
@@ -59,6 +64,7 @@ rating_knowledge: -
59
64
  rating_punctuality: -
60
65
  trips_completed: 0
61
66
  response_rate: 0
67
+ standing: 0
62
68
 
63
69
  ## Route History
64
70
  (builds from booking data)
@@ -80,6 +86,7 @@ All cross-agent state flows through structured files. Never rely on session memo
80
86
  | `shared/dispatch/{jobId}-trip-request.md` | Public agent | Hook → Admin |
81
87
  | `shared/dispatch/{jobId}-booking-confirm.md` | Public agent | Hook → Admin |
82
88
  | `shared/active-negotiations/{phone-digits}.md` | Admin | Hook (driver reply routing) |
89
+ | `shared/active-bookings/{driver-phone-digits}.md` | Admin | Hook (post-booking driver reply routing) |
83
90
  | `shared/offers/{jobId}.md` | Admin | Public agent (when tourist selects) |
84
91
  | `shared/bookings/{jobId}.md` | Admin | Admin (post-payment) |
85
92
  | `shared/state/{tourist-phone}-active.md` | Public agent | Public agent (job ID lookup) |
@@ -152,9 +159,15 @@ destination: [location]
152
159
  date: [date]
153
160
  time: [time]
154
161
  fare: [USD amount]
162
+ duration: [estimated journey minutes from shared/offers/{jobId}.md]
155
163
  payment_url: [Stripe URL]
156
164
  created_at: [timestamp]
157
165
  pin:
166
+ reminder_sent_at:
167
+ acknowledgement_at:
168
+ tourist_checkin_sent_at:
169
+ estimated_arrival:
170
+ rating_requested_at:
158
171
  ```
159
172
 
160
173
  ### Payment Confirmed
@@ -167,7 +180,8 @@ When you receive `[System: Ride Dispatch — Payment Confirmed]`, the message bo
167
180
  4. `message` the tourist with driver details and PIN (exact text in dispatch)
168
181
  5. `message` the driver with the QR code image and booking details (exact text in dispatch)
169
182
  6. `memory_write` to `shared/bookings/{bookingId}.md` — set `status: confirmed`, set `pin: {pin}`
170
- 7. `memory_write` to `shared/active-negotiations/{driver-phone-digits}.md` — empty content
183
+ 7. `memory_write` to `shared/active-negotiations/{driver-phone-digits}.md` — empty content (clears negotiation routing)
184
+ 8. `memory_write` to `shared/active-bookings/{driver-phone-digits}.md` — routing index for post-booking driver messages
171
185
 
172
186
  ### Driver Reply
173
187
 
@@ -184,6 +198,30 @@ When you receive `[System: Ride Dispatch — Driver Reply]`, the message body co
184
198
  1. `memory_write` to `drivers/{name}.md` — set `status: idle`, `current_booking: null`
185
199
  2. `memory_write` to `shared/active-negotiations/{phone-digits}.md` — empty content
186
200
 
201
+ ### Driver Message (Post-Booking)
202
+
203
+ When you receive `[System: Ride Dispatch — Driver Message]`, the driver has messaged during a confirmed booking (after payment, before journey completion). The message body contains step-by-step instructions. Interpret the message and act:
204
+
205
+ STEP 1 — Read the booking record
206
+ `memory_get` on `shared/bookings/{jobId}.md` to load all booking fields (tourist_phone, driver_name, destination, duration, acknowledgement_at, etc.).
207
+
208
+ STEP 1.5 — Record driver acknowledgement
209
+ If `acknowledgement_at` is empty in the booking record, set it now:
210
+ `memory_write` to `shared/bookings/{jobId}.md` — set `acknowledgement_at: [current_time]`.
211
+ This marks that the driver has been in contact regarding this booking, regardless of what the message says.
212
+
213
+ STEP 2 — Interpret and act on the message:
214
+
215
+ - **Pickup confirmed:**
216
+ a. `memory_write` to `shared/bookings/{jobId}.md` — set `status: picked_up`, set `picked_up_at: [current_time]`, set `estimated_arrival: [picked_up_at + duration minutes]`.
217
+ b. `memory_write` to `drivers/{driver_name}.md` — add +1 to `standing`.
218
+ c. Call `message` with channel: "whatsapp", accountId: [WhatsApp account], to: [tourist_phone from booking record].
219
+ Send: "Good news — [driver_name] has confirmed they've picked you up! Enjoy your ride to [destination]."
220
+ - **Driver running late** → message tourist with reassurance
221
+ - **Passenger no-show** → message tourist to come to pickup point; output ALERT in response (not via message tool)
222
+ - **Substitution request** → do NOT approve; output ALERT in response for operator decision
223
+ - **Unclear** → interpret charitably; if genuinely ambiguous, ask driver for clarification
224
+
187
225
  ### Active Negotiation Index
188
226
 
189
227
  `shared/active-negotiations/{phone-digits}.md` format:
@@ -253,6 +291,46 @@ Write a brief note via `memory_write` to `shared/stall-checks/{date}.md`:
253
291
  {timestamp}: Checked {N} stalled jobs. Recovered: {list of jobIds}. Alerted: {list of jobIds}. No action needed: {list of jobIds}.
254
292
  ```
255
293
 
294
+ ### Booking Lifecycle Check
295
+
296
+ When you receive `Run the booking lifecycle check.` (from the lifecycle cron), execute every step below.
297
+
298
+ **STEP 1 — Scan confirmed and picked-up bookings**
299
+ Call `memory_search` on `shared/bookings/` for all files. For each, call `memory_get` and read `status`. Process only bookings with `status: confirmed` or `status: picked_up`.
300
+
301
+ **STEP 2 — Send driver reminder (T−30 min)**
302
+ For each `confirmed` booking where `reminder_sent_at` is empty:
303
+ - Read `date`, `time`, `tourist_name`, `driver_phone`, `pickup`, `job_id`, `account_id`.
304
+ - If pickup time is within 30 minutes from now:
305
+ - Call `message` with channel: "whatsapp", accountId: [account_id], to: [driver_phone].
306
+ - Send exactly: "[job_id] Your pickup is in 30 minutes — [tourist_name] at [pickup]. Please message here when you have collected your passenger. Confirming pickup improves your standing with Beagle, which means you get offered jobs first."
307
+ - `memory_write` to `shared/bookings/{jobId}.md` — set `reminder_sent_at: [current_time]`.
308
+
309
+ **STEP 3 — Tourist check-in (T+15 min, no acknowledgement)**
310
+ For each `confirmed` booking where `acknowledgement_at` is empty and `tourist_checkin_sent_at` is empty:
311
+ - If pickup time was 15+ minutes ago:
312
+ - Call `message` with channel: "whatsapp", accountId: [account_id], to: [tourist_phone].
313
+ - Send exactly: "Just checking — did [driver_name] pick you up okay?"
314
+ - `memory_write` to `shared/bookings/{jobId}.md` — set `tourist_checkin_sent_at: [current_time]`.
315
+
316
+ **STEP 4 — Auto-close (estimated arrival + 60 min)**
317
+ For each `confirmed` or `picked_up` booking:
318
+ - If `estimated_arrival` is set and current time is more than 60 minutes past `estimated_arrival`: auto-close.
319
+ - If `estimated_arrival` is empty and current time is more than 60 minutes past (pickup time + duration): auto-close.
320
+
321
+ Auto-close steps:
322
+ 1. `memory_write` to `shared/bookings/{jobId}.md` — set `status: completed`, set `rating_requested_at: [current_time]`.
323
+ 2. `memory_write` to `shared/active-bookings/{driver_phone_digits}.md` — empty content.
324
+ 3. If `picked_up_at` is empty: `memory_write` to `drivers/{driver_name}.md` — subtract 1 from `standing` (no pickup confirmation).
325
+ 4. Call `message` with channel: "whatsapp", accountId: [account_id], to: [tourist_phone].
326
+ Send: "Hope you enjoyed your ride! How was it? Was everything okay with [driver_name]?"
327
+
328
+ **STEP 5 — Log outcome**
329
+ `memory_write` to `shared/lifecycle-checks/{date}.md`:
330
+ ```
331
+ {timestamp}: Processed {N} bookings. Reminded: {list of jobIds}. Checked-in: {list}. Closed: {list}.
332
+ ```
333
+
256
334
  ### Bookings
257
335
  - Booking records live at `bookings/{job-id}.md` in memory. Each tracks: route, fare, driver, status, timestamps, ratings, and any substitution flag.
258
336
  - Summarise recent booking activity: confirmed, completed, cancelled, no-shows
@@ -266,6 +344,23 @@ Write a brief note via `memory_write` to `shared/stall-checks/{date}.md`:
266
344
  - Track driver state: who is available, who is mid-negotiation, who is booked
267
345
  - Recommend deprioritising unreliable drivers
268
346
 
347
+ ### Standing Score
348
+
349
+ Each driver has a `standing` field in their memory profile (starts at 0). Update it when closing bookings:
350
+
351
+ | Event | Change |
352
+ |-------|--------|
353
+ | Driver acknowledges 30-min reminder | +1 |
354
+ | Driver confirms pickup | +1 |
355
+ | No acknowledgement — tourist check-in was required | −1 |
356
+ | No pickup confirmation — job auto-closed | −1 |
357
+ | No-show or unannounced substitution | −2 |
358
+
359
+ When selecting drivers for a new trip request, rank idle candidates by:
360
+ 1. `standing` descending
361
+ 2. Average tourist rating descending (across all 5 rating dimensions)
362
+ 3. Route history match (as tiebreaker)
363
+
269
364
  ### Driver Substitution Follow-up
270
365
 
271
366
  When a substitution is flagged in a booking record:
@@ -0,0 +1,20 @@
1
+ {
2
+ "templateId": "beagle-zanzibar-lifecycle-check",
3
+ "name": "Booking Lifecycle Check",
4
+ "description": "Runs every 10 minutes. Sends driver reminders 30 minutes before pickup, tourist check-ins if the driver hasn't acknowledged, and auto-closes bookings 1 hour after estimated arrival, sending a rating request.",
5
+ "enabled": true,
6
+ "agentId": "beagle-zanzibar-admin",
7
+ "schedule": { "kind": "cron", "expr": "*/10 * * * *" },
8
+ "sessionTarget": "isolated",
9
+ "wakeMode": "next-heartbeat",
10
+ "payload": {
11
+ "kind": "agentTurn",
12
+ "message": "Run the booking lifecycle check.",
13
+ "deliver": false,
14
+ "bestEffortDeliver": false
15
+ },
16
+ "isolation": {
17
+ "postToMainMode": "summary",
18
+ "postToMainPrefix": "Lifecycle Check"
19
+ }
20
+ }
@@ -73,13 +73,13 @@ You will see these messages appear in your conversation via cross-agent echo. Ac
73
73
 
74
74
  ## Driver Pickup Reminders
75
75
 
76
- The operations agent handles driver reminders for advance bookings via its periodic heartbeat:
76
+ The admin agent's Booking Lifecycle Check cron runs every 10 minutes and manages:
77
77
 
78
- 1. **Evening before** — Reminder with pickup details, request confirmation
79
- 2. **2 hours before** — Second reminder, request confirmation
80
- 3. **30 minutes before** — Final reminder
78
+ 1. **30 minutes before pickup** — driver reminder via WhatsApp, asking them to message when they've collected the passenger. The reminder explains that confirming pickup improves their standing.
79
+ 2. **15 minutes after pickup (no driver acknowledgement)** — tourist check-in: "Just checking — did [driver] pick you up okay?"
80
+ 3. **Estimated arrival + 60 minutes** — auto-close: status set to `completed`, rating request sent to tourist.
81
81
 
82
- If a driver doesn't confirm, the operations agent escalates — attempting to reach the driver again or sourcing a replacement. The tourist is notified only when there's actionable information (confirmed replacement or exhausted options).
82
+ Driver acknowledgement of the reminder triggers a tourist reassurance message: "[Driver name] has confirmed they're on their way."
83
83
 
84
84
  ## Booking Record
85
85
 
@@ -92,12 +92,26 @@ Every confirmed booking is recorded by the operations agent at `shared/bookings/
92
92
  - **Driver** — name, WhatsApp number, vehicle, plate
93
93
  - **Fare** — negotiated amount, booking fee amount, Stripe payment ID
94
94
  - **PIN** — the 4-digit pickup code
95
- - **Status** — one of: `confirmed`, `reminded`, `picked_up`, `completed`, `cancelled`, `no_show`
95
+ - **Duration** — estimated journey minutes (from driver offer)
96
+ - **Lifecycle timestamps** — `reminder_sent_at`, `acknowledgement_at`, `tourist_checkin_sent_at`, `estimated_arrival`, `rating_requested_at`
97
+ - **Status** — one of: `payment_pending`, `confirmed`, `picked_up`, `completed`, `cancelled`, `no_show`
96
98
  - **Timestamps** — when each status transition occurred
97
99
  - **Rating** — post-ride ratings (added after feedback)
98
100
 
99
101
  The admin agent uses these records for operational oversight — booking summaries, driver reliability tracking, and dispute resolution.
100
102
 
103
+ ## Driver Standing
104
+
105
+ Each driver has a `standing` score that affects their priority for new jobs. Standing is updated by the admin agent:
106
+
107
+ - **+1** for acknowledging the 30-min reminder
108
+ - **+1** for confirming pickup
109
+ - **−1** for no acknowledgement (tourist check-in was required)
110
+ - **−1** for no pickup confirmation (auto-close without confirmation)
111
+ - **−2** for no-show or unannounced substitution
112
+
113
+ When the admin selects drivers for a new trip request, candidates are ranked: standing (highest first) → average tourist rating → route history.
114
+
101
115
  ## Edge Cases
102
116
 
103
117
  **Tourist wants to cancel after payment:** Explain the booking fee is non-refundable (commitment device for both sides). Offer to reschedule at no extra charge.