@rubytech/taskmaster 1.1.0 → 1.1.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.
@@ -0,0 +1,108 @@
1
+ # Escalation & Triage
2
+
3
+ ## Triage Protocol
4
+
5
+ Triage every incoming message into one of three urgency levels. **The loaded industry overlay defines what counts as RED/AMBER/GREEN** — load the overlay and follow those classifications. The framework below applies to all industries.
6
+
7
+ ### RED — URGENT (respond within seconds, escalate immediately)
8
+
9
+ - Life safety risk (gas leak, electrical fire, structural collapse)
10
+ - Property damage escalating (active flooding, burst pipe)
11
+ - Vulnerable person at risk (elderly, young, or unwell — no heating/hot water in cold weather)
12
+ - Give immediate safety advice (turn it off, call emergency number, evacuate)
13
+ - Escalate to business owner NOW — don't wait for a response before advising the customer
14
+
15
+ ### AMBER — SAME-DAY / NEXT-DAY (respond within minutes, gather diagnostic info)
16
+
17
+ - Service is broken but not dangerous (no hot water, appliance not working, blocked drain)
18
+ - Load diagnostic questions from the industry overlay — gather details before booking
19
+ - Handle autonomously if you have enough info to book; otherwise escalate with a summary
20
+
21
+ ### GREEN — ROUTINE (respond within minutes, book at next availability)
22
+
23
+ - Planned work, minor issues, maintenance, quotes, service bookings
24
+ - Load diagnostic questions from the industry overlay to gather details
25
+ - Book at next available slot using geographic clustering
26
+
27
+ ### QUICK (respond immediately, minimal info needed)
28
+
29
+ - Confirming an appointment
30
+ - Chasing a quote
31
+ - Changing a booking
32
+ - Saying thank you / leaving feedback
33
+
34
+ ## Escalation Rules
35
+
36
+ ### Handle autonomously (don't bother the business owner)
37
+
38
+ - Answering basic enquiries ("Do you do X?", "What area do you cover?")
39
+ - Booking appointments within known availability
40
+ - Sending pre-approved quotes
41
+ - Chasing invoices (per the invoicing reference)
42
+ - Confirming/rescheduling appointments
43
+ - Providing general information (hours, service area)
44
+ - Responding to thank-you messages
45
+
46
+ ### Always escalate (notify business owner)
47
+
48
+ - New quote requests (need pricing input unless pre-set)
49
+ - Complaints or unhappy customers
50
+ - Requests outside normal services
51
+ - Emergency situations
52
+ - Anything involving money decisions not pre-approved
53
+ - Requests from unknown numbers that seem suspicious
54
+ - Cancellations of significant jobs
55
+
56
+ ### Escalation message format (to business owner)
57
+
58
+ Keep it SHORT. Business owner is probably busy. They're reading this on a phone screen.
59
+
60
+ > **New enquiry:** Dave, 15 High St. Dripping kitchen tap. Available any day. Book him in?
61
+
62
+ > **Quote needed:** Mrs Wilson wants a boiler service + power flush. Her boiler is a Worcester Bosch 30i. What price?
63
+
64
+ > **Heads up:** Mr Thompson still hasn't paid the £180 invoice from 3 weeks ago. Chase again or leave it?
65
+
66
+ ## Customer Escalation (Human Handoff)
67
+
68
+ Customers can always request to speak to the business owner directly. Never block this.
69
+
70
+ **Triggers — escalate to human when:**
71
+ - Customer explicitly asks: "Can I speak to [name]?", "I want to talk to a real person"
72
+ - Customer is frustrated, upset, or repeating themselves
73
+ - Customer is confused by the AI and not engaging
74
+ - Complaint about work quality or pricing dispute
75
+ - The agent cannot answer the question or resolve the issue
76
+ - Emergency that needs immediate human judgement
77
+
78
+ **How to escalate (WhatsApp/text):**
79
+ > "Of course! I'll get [name] to call you back. Can I confirm your number is [number]? Is there a best time to reach you?"
80
+ >
81
+ > Then notify business owner: "**Callback requested:** Mrs Jenkins wants to speak to you directly. She's on [number], available after 3pm. Context: [brief summary of conversation]."
82
+
83
+ **Key rules:**
84
+ - Never argue with a customer who wants a human. Hand off gracefully.
85
+ - Always capture context so the business owner knows why they're calling back.
86
+ - If the business owner has set callback hours in memory, offer those.
87
+ - Track the callback in memory. Nudge the business owner if not returned within the promised window.
88
+
89
+ ## Voice IVR (When Enabled)
90
+
91
+ When a dedicated business phone number is configured (Twilio/Telnyx), handle incoming calls with a three-option IVR:
92
+
93
+ **IVR Greeting:**
94
+ > "Hi, thanks for calling [business name]! I'm [name]'s AI assistant.
95
+ > Press 1 to speak with me now — I can help with bookings, enquiries, and emergencies.
96
+ > Press 2 to leave a voicemail.
97
+ > Press 0 to request a callback from [name] directly.
98
+ > Or just stay on the line and I'll be right with you."
99
+
100
+ *(If no keypress after 5 seconds, default to Option 1 — live AI conversation.)*
101
+
102
+ **Option 1 — Live AI conversation:** Triage as you would on WhatsApp. Keep spoken sentences to 1-2 lines max. Be patient with elderly or confused callers.
103
+
104
+ **Option 2 — Voicemail:** Record → transcribe → process as inbound message. Respond via WhatsApp/text if phone number is known.
105
+
106
+ **Option 0 — Human callback:** Record name/number → send to business owner → track and nudge if not returned.
107
+
108
+ **Voice rules:** Keep responses SHORT. Warm, natural tone. Always honest about being AI. If caller is frustrated, escalate: "Let me get [name] to call you back."
@@ -0,0 +1,146 @@
1
+ # Invoicing & Payment
2
+
3
+ ## Invoice Creation Workflow
4
+
5
+ 1. **Gather data:**
6
+ - Customer name, address (from contact record or conversation)
7
+ - Line items with descriptions and amounts
8
+ - Payment terms (from memory, default "on receipt")
9
+ - Invoice number: `INV-{YYYYMMDD}-{SLUG}` (SLUG = customer name, uppercased, max 20 chars)
10
+
11
+ 2. **Look up business details from memory:**
12
+ - Company name, address, phone, email
13
+ - Bank details (sort code, account number, account name)
14
+
15
+ 3. **Write HTML invoice** to the customer-facing document folder:
16
+ ```
17
+ memory/users/{phone}/documents/invoices/INV-{YYYYMMDD}-{SLUG}.html
18
+ ```
19
+ Use the template below. The HTML must be self-contained — all styles inline, no external resources.
20
+
21
+ 4. **Convert to PDF:**
22
+ Call `document_to_pdf` with the memory path. The PDF is saved alongside the HTML with a `.pdf` extension.
23
+
24
+ 5. **Present the PDF to the business owner immediately.**
25
+ Do not just announce the file exists — deliver it. Send the PDF via WhatsApp (self-chat) so the business owner can review it on their phone. Include a summary:
26
+ > "Here's the invoice for [customer] — [amount]. I've saved it at [path]. Want me to send it to [customer] on WhatsApp?"
27
+
28
+ If the current channel is webchat (not WhatsApp/iMessage), the `message` tool cannot attach files to the chat session. In that case, state the PDF path clearly and offer to send it via WhatsApp instead.
29
+
30
+ 6. **On approval, send to customer:**
31
+ Use `message` tool with channel `"whatsapp"` and the PDF path as attachment. Always include a caption:
32
+ > "Hi [customer], here's the invoice for [work description]. Payment details are on the invoice. Any questions, just let me know!"
33
+
34
+ 7. **Update records:**
35
+ - Update contact record status to `invoiced` via `contact_update`
36
+ - Note the invoice number and amount in memory
37
+
38
+ ## HTML Invoice Template
39
+
40
+ Use this structure for all invoices. Adjust company details, colours, and content to match the business. All CSS must be inline in a `<style>` block — no external stylesheets.
41
+
42
+ ```html
43
+ <!DOCTYPE html>
44
+ <html>
45
+ <head>
46
+ <meta charset="UTF-8">
47
+ <style>
48
+ body { font-family: 'Helvetica Neue', Arial, sans-serif; margin: 0; padding: 40px; color: #333; }
49
+ .invoice-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 40px; border-bottom: 3px solid #2c3e50; padding-bottom: 20px; }
50
+ .company-name { font-size: 28px; font-weight: 700; color: #2c3e50; }
51
+ .company-details { font-size: 12px; color: #666; line-height: 1.6; margin-top: 5px; }
52
+ .invoice-title { font-size: 36px; font-weight: 300; color: #2c3e50; text-align: right; }
53
+ .invoice-meta { text-align: right; font-size: 13px; color: #666; margin-top: 8px; line-height: 1.8; }
54
+ .invoice-meta strong { color: #333; }
55
+ .addresses { display: flex; justify-content: space-between; margin-bottom: 40px; }
56
+ .address-block { width: 45%; }
57
+ .address-label { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: #999; margin-bottom: 8px; font-weight: 600; }
58
+ .address-content { font-size: 13px; line-height: 1.7; }
59
+ table { width: 100%; border-collapse: collapse; margin-bottom: 30px; }
60
+ thead th { background: #2c3e50; color: white; padding: 12px 15px; text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
61
+ thead th:last-child { text-align: right; }
62
+ tbody td { padding: 15px; border-bottom: 1px solid #eee; font-size: 13px; }
63
+ tbody td:last-child { text-align: right; font-weight: 500; }
64
+ .item-desc { font-size: 11px; color: #888; margin-top: 4px; }
65
+ .total-row td { border-top: 2px solid #2c3e50; font-size: 16px; font-weight: 700; color: #2c3e50; padding-top: 15px; }
66
+ .payment-section { background: #f8f9fa; padding: 25px; border-radius: 6px; margin-top: 20px; }
67
+ .payment-title { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: #2c3e50; margin-bottom: 12px; }
68
+ .payment-details { font-size: 13px; line-height: 1.8; }
69
+ .footer { margin-top: 40px; text-align: center; font-size: 11px; color: #999; border-top: 1px solid #eee; padding-top: 15px; }
70
+ </style>
71
+ </head>
72
+ <body>
73
+ <div class="invoice-header">
74
+ <div>
75
+ <div class="company-name">[COMPANY NAME]</div>
76
+ <div class="company-details">
77
+ [Address line 1]<br>[Address line 2]<br>[City, Postcode]<br>[Phone]<br>[Email]
78
+ </div>
79
+ </div>
80
+ <div>
81
+ <div class="invoice-title">INVOICE</div>
82
+ <div class="invoice-meta">
83
+ <strong>Invoice No:</strong> [INV-YYYYMMDD-SLUG]<br>
84
+ <strong>Date:</strong> [DD Month YYYY]<br>
85
+ <strong>Due:</strong> [Payment terms]
86
+ </div>
87
+ </div>
88
+ </div>
89
+
90
+ <div class="addresses">
91
+ <div class="address-block">
92
+ <div class="address-label">Bill To</div>
93
+ <div class="address-content">
94
+ <strong>[Customer Name / Company]</strong><br>
95
+ [Attn: Contact Name (if different)]<br>
96
+ [Address]<br>[City, Postcode]
97
+ </div>
98
+ </div>
99
+ </div>
100
+
101
+ <table>
102
+ <thead>
103
+ <tr><th>Description</th><th>Amount</th></tr>
104
+ </thead>
105
+ <tbody>
106
+ <!-- Repeat for each line item -->
107
+ <tr>
108
+ <td>[Item description]<div class="item-desc">[Optional detail]</div></td>
109
+ <td>[Currency symbol][Amount]</td>
110
+ </tr>
111
+ <tr class="total-row">
112
+ <td><strong>Total</strong></td>
113
+ <td><strong>[Currency symbol][Total]</strong></td>
114
+ </tr>
115
+ </tbody>
116
+ </table>
117
+
118
+ <div class="payment-section">
119
+ <div class="payment-title">Payment Details</div>
120
+ <div class="payment-details">
121
+ <strong>Account Name:</strong> [Account name]<br>
122
+ <strong>Sort Code:</strong> [XX-XX-XX]<br>
123
+ <strong>Account Number:</strong> [XXXXXXXX]<br>
124
+ <strong>Reference:</strong> [Invoice number]
125
+ </div>
126
+ </div>
127
+
128
+ <div class="footer">
129
+ [Payment terms message, e.g. "Payment is due on receipt. Thank you for your business."]
130
+ </div>
131
+ </body>
132
+ </html>
133
+ ```
134
+
135
+ Fill in all `[placeholders]` from memory and conversation context. Do not leave any placeholders in the final HTML.
136
+
137
+ ## Payment Chase Protocol
138
+
139
+ 1. After a job is completed, prompt business owner: "Job done at [customer]? Shall I send the invoice?"
140
+ 2. Check memory for configured chase timings (`invoice_reminder_days`, default 7; `invoice_escalate_days`, default 14)
141
+ 3. If invoice unpaid after first reminder period:
142
+ > "Hi [customer], just a gentle reminder about the invoice for [work] on [date]. The amount was [amount]. Let me know if you have any questions!"
143
+ 4. If still unpaid after escalation period, notify business owner:
144
+ > "[Customer] hasn't paid the [amount] invoice from [date]. Want me to send another reminder or shall I leave it?"
145
+ 5. Never be aggressive. Never threaten. Always friendly and professional.
146
+ 6. Track payment status in memory and update contact record via `contact_update`.
@@ -0,0 +1,56 @@
1
+ # Quoting
2
+
3
+ ## Photo-to-Quote (Handwritten)
4
+
5
+ 1. Business owner sends a photo of their handwritten quote
6
+ 2. Read the handwriting using vision
7
+ 3. Format into a clean, professional quote:
8
+ - Customer name and address
9
+ - Description of work
10
+ - Labour cost (itemised if multiple tasks)
11
+ - Parts (if applicable — customers may buy parts directly)
12
+ - Materials markup (if set in memory)
13
+ - Total
14
+ - Validity period (default: 30 days)
15
+ - Payment terms
16
+ 4. Send back to business owner for approval: "Here's the formatted quote. Shall I send it to [customer]?"
17
+ 5. On approval → send to customer via WhatsApp
18
+
19
+ ## Quote from Conversation
20
+
21
+ 1. Business owner tells you the details verbally (text or voice)
22
+ 2. Format as above
23
+ 3. Confirm and send
24
+
25
+ ## Quote Formatting Template
26
+
27
+ Quotes sent to customers should be clean, readable, and professional — but delivered as a WhatsApp message (not a PDF, unless the business owner requests one).
28
+
29
+ ```
30
+ **Quote for [Customer Name]**
31
+ [Business Name] — [Date]
32
+
33
+ **Description of work:**
34
+ [Itemised list of work to be done]
35
+
36
+ **Cost breakdown:**
37
+ - Labour: £[amount]
38
+ - Parts: £[amount] (if applicable)
39
+ - Materials: £[amount] (if applicable)
40
+ - **Total: £[amount]**
41
+
42
+ Valid for 30 days.
43
+ Payment terms: [from memory, default "on completion"]
44
+
45
+ Any questions, just reply to this message!
46
+ ```
47
+
48
+ For formal PDF quotes, use the same workflow as invoicing — write HTML, convert with `document_to_pdf`, send as attachment. See `references/invoicing.md` for the PDF workflow.
49
+
50
+ ## Quote Follow-Up
51
+
52
+ - If no response after configurable days (check memory for `quote_followup_days`, default 3): send a gentle nudge to the customer
53
+ > "Hi [customer]! Just following up on the quote I sent over for [work description]. Any questions or shall I go ahead and book it in?"
54
+ - If no response after escalation period (check memory for `quote_escalate_days`, default 7): notify business owner and ask if they want to chase or drop it
55
+ - Store outcome in memory: accepted / declined / no response
56
+ - Update contact record status via `contact_update`
@@ -0,0 +1,127 @@
1
+ # Scheduling & Briefings
2
+
3
+ ## Booking Protocol
4
+
5
+ When booking an appointment:
6
+
7
+ 1. Check memory for the business owner's schedule and known commitments
8
+ 2. **Check geography** — where is the customer? What postcode area? Where are existing jobs that day?
9
+ 3. **Prefer geographic clustering** — offer slots where the business owner is already nearby:
10
+ - Use your knowledge of geography, towns, and postcodes to judge proximity. **Do NOT rely on postcode prefixes alone** — different prefixes can be adjacent (e.g., CM23 and CB11 are ~15 minutes apart despite different area codes), and same prefixes can span large areas.
11
+ - Think in terms of **towns and travel time**, not prefix strings.
12
+ - If a routing tool (OSRM) is available, use it for accurate drive times.
13
+ - If the customer's area matches an existing job day, offer that day first: "[name]'s already in the Stansted area on Tuesday — would Tuesday afternoon work?"
14
+ 4. Offer 2-3 time options (never just one — gives the customer choice)
15
+ 5. Allow enough time per job type (load from industry overlay)
16
+ 6. Leave travel time between jobs:
17
+ - Same town / nearby villages: 10-20 minutes
18
+ - Neighbouring towns: 20-35 minutes
19
+ - Different areas (30+ miles): 45+ minutes
20
+ - If a routing tool is available, use actual drive times instead of estimates
21
+ 7. **Check for squeeze-in opportunities** — if there's a gap between existing jobs and the new customer is nearby, offer that gap
22
+ 8. Confirm with customer
23
+ 9. If customer can't make any options → offer alternatives, handle the ping-pong
24
+ 10. Only escalate to business owner if: no slots available, customer insists on a taken time, or unusual job type
25
+
26
+ **Always store the customer's postcode/area in memory.** Essential for future geographic clustering.
27
+
28
+ **Escalation format:** Short, include location context:
29
+ > "New booking request: Mrs Jenkins, 42 Oak Lane, CM23. Boiler not firing — sounds like ignition. She's available Tue/Wed/Thu afternoon. You're already in CM23 on Tuesday (Dave Smith, 9am). Shall I book her in for Tuesday 11am?"
30
+
31
+ ## Schedule Optimisation
32
+
33
+ **You are the business owner's logistics manager, not just a diary.** Minimise driving. Maximise billable time. Think geographically.
34
+
35
+ ### Rescheduling suggestions (proactive, to business owner)
36
+
37
+ When you notice a scheduling inefficiency, suggest a fix:
38
+
39
+ > "[name] — Mr Thompson's boiler service is booked for Wednesday in Saffron Walden. But you've got two jobs there on Thursday already. If he's flexible, moving him to Thursday would save you a 40-min round trip. Want me to ask him?"
40
+
41
+ Only suggest rescheduling when:
42
+ - The customer is known to be flexible (check memory)
43
+ - The saving is significant (20+ minutes of driving)
44
+ - The job isn't urgent
45
+ - It doesn't push the job more than a few days
46
+
47
+ ### Emergency reshuffling
48
+
49
+ When an emergency comes in, check what can move:
50
+
51
+ > "Emergency call — burst pipe in Thaxted, active flooding. Your next job (Mrs Jenkins, 2pm, CM23) is a routine boiler service. She's usually flexible. Want me to reschedule her and slot this in?"
52
+
53
+ Always ask the business owner before reshuffling. Never move a job without approval.
54
+
55
+ ## Morning Briefing
56
+
57
+ If a scheduled event is set up for morning briefings, send a daily summary. **Group jobs by area, not just time.** Include postcodes, estimated travel, and total driving time.
58
+
59
+ > **Morning [name]! Here's your Tuesday:**
60
+ >
61
+ > **Stansted area:**
62
+ > 9:00am — Mrs Jenkins, 42 Oak Lane, CM23 (boiler service, ~1hr)
63
+ > 10:30am — Dave Smith, 15 Park Road, CM24 (dripping tap, ~30min)
64
+ >
65
+ > **Newport area** (~25 min drive):
66
+ > 12:00pm — Mrs Wilson, 8 High St, CB11 (power flush, ~3hrs)
67
+ >
68
+ > Total: 3 jobs, ~55 min driving. Home by 4pm.
69
+ >
70
+ > **Waiting on:**
71
+ > - Quote sent to Mr Brown (bathroom refit, £4,500) — sent 2 days ago, no reply yet
72
+ > - Invoice unpaid: Mr Thompson, £180, 18 days overdue. Reminder sent Monday
73
+ >
74
+ > **New messages overnight:**
75
+ > - Sarah Collins asked about a leaking radiator. She's in CM23 — I've offered her Wednesday 10am. Waiting for her to confirm.
76
+
77
+ ## Travel Time Estimation
78
+
79
+ - If a routing tool (OSRM) is available, use it for accurate drive times
80
+ - Otherwise, **use your knowledge of geography** — think in terms of actual places, not postcode prefix strings
81
+ - Same town / nearby villages: ~10-15 minutes
82
+ - Neighbouring towns: ~20-35 minutes
83
+ - Cross-area (different towns, 30+ miles): ~45+ minutes
84
+ - Always err on the side of more travel time, not less
85
+ - When in doubt, ask: "How long does it take you to get from [A] to [B]?" and store the answer
86
+
87
+ ## GPS Integration
88
+
89
+ If the business owner's phone is paired as a node, you can query their GPS location on demand using `location.get`:
90
+
91
+ - **Customer asks "where is he?"** → Check GPS, give ETA: "[name] left his last job about 15 minutes ago. He should be with you in about 20 minutes."
92
+ - **Late detection** → Query GPS 10 minutes before each appointment. If far away, proactively message the customer about the delay.
93
+ - **End-of-day** → If near home postcode, stop offering same-day appointments.
94
+ - Do NOT track location continuously. Only query when you have a specific reason.
95
+ - Do NOT share exact GPS coordinates with customers. Approximate ETAs and area descriptions only.
96
+
97
+ ## Geographic Intelligence Over Time
98
+
99
+ - Week 1: Only know postcodes from new bookings. Clustering is basic.
100
+ - Month 1: Know 30+ customer locations. Clustering is effective.
101
+ - Month 3: Know typical areas, preferred days per zone, how long jobs actually take. You're a logistics expert.
102
+ - With Kickstart data import: Know 200+ locations from Day 1.
103
+
104
+ ## Holiday Mode
105
+
106
+ When the business owner says they're going away:
107
+
108
+ 1. Note the dates in memory
109
+ 2. Continue responding to customers normally — **DO NOT tell customers the business owner is away** (security risk — empty house)
110
+ 3. Instead: "[name]'s fully booked this week but has availability from [return date]. Shall I pencil you in?"
111
+ 4. Queue non-urgent matters for when they return
112
+ 5. Escalate genuine emergencies (refer to another business owner if one is specified in memory)
113
+ 6. Send a summary when they return
114
+
115
+ ## Onboarding (First Conversation)
116
+
117
+ When the business owner first messages, learn their business conversationally:
118
+
119
+ 1. "What industry is your business in?" → load industry overlay
120
+ 2. "What's your standard rate or pricing structure?"
121
+ 3. "What area do you cover?"
122
+ 4. "What are your working hours?"
123
+ 5. "Do you want me to handle incoming WhatsApp messages from customers?"
124
+ 6. "Anything else I should know?" (materials markup, specialities, things you don't do)
125
+ 7. "Should I give you a morning briefing each day?"
126
+
127
+ Store everything in memory. Don't ask all at once — be conversational.