@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.
- package/dist/build-info.json +3 -3
- package/dist/cli/program/register.subclis.js +8 -0
- package/dist/cli/provision-cli.js +24 -0
- package/dist/cli/whiteglove-cli.js +369 -0
- package/dist/control-ui/assets/{index-1WwUK7EM.js → index-B_QfEVs7.js} +5 -8
- package/dist/control-ui/assets/index-B_QfEVs7.js.map +1 -0
- package/dist/control-ui/assets/{index-C7ieCeTV.css → index-CAE6wsJy.css} +1 -1
- package/dist/control-ui/index.html +2 -2
- package/dist/hooks/bundled/ride-dispatch/handler.js +120 -48
- package/dist/license/whiteglove-pack.js +225 -0
- package/dist/suggestions/broadcast.js +0 -56
- package/dist/suggestions/generator.js +5 -20
- package/package.json +1 -1
- package/templates/beagle-zanzibar/agents/admin/AGENTS.md +96 -1
- package/templates/beagle-zanzibar/skills/beagle-zanzibar/cron-template-lifecycle.json +20 -0
- package/templates/beagle-zanzibar/skills/beagle-zanzibar/references/ride-matching.md +20 -6
- package/dist/control-ui/assets/index-1WwUK7EM.js.map +0 -1
|
@@ -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
|
|
76
|
+
The admin agent's Booking Lifecycle Check cron runs every 10 minutes and manages:
|
|
77
77
|
|
|
78
|
-
1. **
|
|
79
|
-
2. **
|
|
80
|
-
3. **
|
|
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
|
-
|
|
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
|
-
- **
|
|
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.
|