docs(dn): Foreman inbox-clerk skill and the Claude review skill
Foreman (MiniMax) works the delivery-note inbox: checks every slip against its photo and PO, fixes misreads, groups kits, prepares clean slips with prepare_delivery (Ready to post, never booked) and asks the site about the rest. The review skill spot-checks his work, moves answered site questions on to Ready to post and applies site-confirmed receipt corrections. The site manager pulls the trigger. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0307d2cb35
commit
009ac0e30f
2 changed files with 147 additions and 0 deletions
53
.claude/skills/dn-inbox-review/SKILL.md
Normal file
53
.claude/skills/dn-inbox-review/SKILL.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
name: dn-inbox-review
|
||||
description: Review Foreman's latest delivery-note inbox run. Spot-check what he prepared against the photos, move answered site questions on to Ready to post, apply site-confirmed receipt corrections, and write a short report. Never books.
|
||||
---
|
||||
|
||||
# Delivery-note inbox review (after Foreman)
|
||||
|
||||
Foreman (MiniMax) works the inbox first: skill `foreman/skills/dn-inbox/SKILL.md`. His reports are in `foreman/runs/dn-inbox/<YYYY-MM-DD-HH-MM>.md`. You are the second, smaller check before the site manager pulls the trigger. Use the MegaDash MCP tools (`megadash-direct`, or the MEGADASH connector). Never write to PocketBase directly.
|
||||
|
||||
## 1. Read Foreman's latest report
|
||||
- Open the newest file in `foreman/runs/dn-inbox/`. If it is older than this morning or says the run failed, say so at the top of your report and work the board directly (steps 2–4 still apply).
|
||||
- Use its "For the reviewer" table as your checklist.
|
||||
|
||||
## 2. Spot-check what he prepared (Ready to post)
|
||||
For every document Foreman moved to Ready to post (and anything else on `inbox_board` in `ready_to_post`):
|
||||
1. `get_delivery_candidate`, then open the photo (`read_document`, `kind:"page"`). Look at it yourself, and zoom into the handwritten Quantity Delivered column.
|
||||
2. For every saved allocation (`reconciliation_preview.allocations[]`), check:
|
||||
- The quantity matches the photo, in the PO's unit (6 m lengths, kg → t, kits).
|
||||
- The PO line is the right one.
|
||||
- NIL lines are closed.
|
||||
3. Check the money: `netTotal` against the slip's printed excl-VAT total, where it prints one. The difference must be explained by noted price differences (PO rate vs slip price). Check against `get_purchase_order_detail` that nothing goes over the PO.
|
||||
4. Wrong → fix the line, re-run `process_delivery_candidate` and `prepare_delivery` with the right plan. Can't tell → `request_site_decision`. Write down what you changed and why.
|
||||
- Low-confidence rows in Foreman's table get a full check, line by line.
|
||||
- High-confidence rows: check at least the handwritten column and the total.
|
||||
|
||||
## 3. Waiting for site: answered questions
|
||||
For each document whose site question has been answered (`get_delivery_candidate` → `checks` entry `site_decision` with `passed:true` and `detail.answer`):
|
||||
- Apply the answer. Link the PO they named (`resolve_delivery_entities`), fix quantities or units, upload the PO if they said it's coming and it's now in the system, or set aside if they said so.
|
||||
- If they approved an extra quantity over the PO, `prepare_delivery` with `acceptExcess:true` and a reason quoting their answer.
|
||||
- Then `prepare_delivery`, so it lands in Ready to post. Check it as in step 2.
|
||||
- An answer that confirms a **posted** receipt is wrong (e.g. Global Precast 61833: 65 pipes × 2.5 m = 162.5 m, not 65 m) → `reassign_receipt` with the expected current quantity and the site's answer as the reason.
|
||||
- An answer you can't act on, or a vague one → ask a follow-up `request_site_decision`.
|
||||
- Questions still open: leave them, and count them in your report.
|
||||
|
||||
## 4. Foreman's other findings
|
||||
- "Posted receipts that look wrong": verify against the photo and PO. Fix with `reassign_receipt` only when the photo or a site answer proves it. Otherwise ask the site.
|
||||
- Supplier duplicates: `merge_suppliers` only when the names, registration or VAT numbers show it's the same company. Otherwise list it for David.
|
||||
- Flags for deletion: check the reason holds, and leave them for David.
|
||||
|
||||
## Rules
|
||||
- **Never book**: no `post_delivery`, `post_delivery_line`, `correct_delivery_receipt`. The site manager presses Confirm delivery.
|
||||
- Never accept an excess without a site answer that approves it.
|
||||
- Never delete. Use `request_deletion` with a reason.
|
||||
- Every write: a new UUID v4 `operationId` and a reason.
|
||||
|
||||
## Your report
|
||||
Write it to `foreman/runs/dn-inbox-review/<YYYY-MM-DD-HH-MM>.md` and also give it as your final message:
|
||||
- Line 1: `REVIEW: OK` (nothing needs David) or `REVIEW: ATTENTION (<n>)`.
|
||||
- **Ready for the site manager**: per site, document, supplier, PO, total excl VAT, "checked". This is the list they confirm from.
|
||||
- **What I changed**: tool, document, reason.
|
||||
- **Where Foreman was wrong**: so his skill can be improved, with the exact mistake.
|
||||
- **Waiting for site**: count per site and the oldest question's age.
|
||||
- **Needs David**: anything that is a decision for him, e.g. a deletion, a supplier merge, a price dispute.
|
||||
94
foreman/skills/dn-inbox/SKILL.md
Normal file
94
foreman/skills/dn-inbox/SKILL.md
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
---
|
||||
name: dn-inbox
|
||||
description: Works the delivery-note inbox. Checks every open slip against its photo and PO, fixes what the reader got wrong, prepares clean slips for the site manager (Ready to post, never booked), asks the site about anything it can't decide, and reports every change.
|
||||
---
|
||||
|
||||
# Delivery-note inbox clerk
|
||||
|
||||
## Goal
|
||||
Every open delivery document ends the run in one of these places, with the real reason written down:
|
||||
- **Ready to post**: you checked it against the photo and the PO, saved the plan with `prepare_delivery`, and the totals add up. The site manager only checks the totals and presses Confirm.
|
||||
- **Waiting for site**: you asked the site one plain question (`request_site_decision`) that a person on site can answer.
|
||||
- **Set aside**: it isn't a delivery document (quotation, a PO photo, a duplicate, a hire contract the site said to set aside).
|
||||
- **In your report**: anything you could not do, with what blocked you.
|
||||
|
||||
Done well means: nothing is booked by you, no quantity is guessed, every number you saved matches the photo, and the report lets the reviewer re-check your work quickly.
|
||||
|
||||
## Where to look
|
||||
- The MegaDash app tools (MCP server `megadash-direct`). These are the only way to read or change the app. Never write to PocketBase directly.
|
||||
- Start with `inbox_board`. It lists every open document (`documents`), batches waiting for page grouping (`groupingBatches`), and records flagged for deletion. Use `inbox_board` with `site` to work one site at a time.
|
||||
- Per document: `get_delivery_candidate` (lines, checks, saved plan, page ids), `get_purchase_order_detail` (PO lines with ordered / delivered / outstanding), `list_purchase_orders` (find a PO by site), and `read_document` with `kind:"page"` and the page id (the photo, as base64).
|
||||
- Look at every photo yourself. Save it to a file (`/tmp/foreman-dn/<batchId>-p<page>.png`) and open it. To read a handwritten column, crop and enlarge that part of the image locally (e.g. `python3 -c` with PIL, or `sips`). **If you cannot see images, stop and say so in the report. Do not prepare anything without reading the photo.**
|
||||
|
||||
## How to work each item
|
||||
|
||||
Work **one PO at a time**, and finish each slip before the next. Saving or booking one slip makes the other slips on the same PO "stale" (re-run `process_delivery_candidate` on them before `prepare_delivery`).
|
||||
|
||||
### A. Batches waiting for grouping (`groupingBatches`)
|
||||
1. Open each page photo. Decide what is on it: one document, several pages of one document, or two documents on one photo.
|
||||
2. One complete document with other paper only in the background → `set_delivery_grouping` with that page as its own group, then `process_delivery_batch`. The re-read can take a few minutes. Come back to it at the end of the run.
|
||||
3. Two complete documents on one photo → `split_or_crop_page` with one region per document (fractions 0–1 of the image, with a little margin). The crops become new uploads and the original is set aside. Note the new batch ids in the report.
|
||||
4. A page that isn't a delivery document (blank, a PO, a quotation) → leave the grouping to the site with `request_site_decision`, or use `move_to_purchase_orders` for a PO photo (see C).
|
||||
|
||||
### B. Documents waiting for site (board `next` starts with "waiting for site")
|
||||
- Leave them alone. The reviewer handles answered questions. Just list them in the report.
|
||||
|
||||
### C. Every other open document
|
||||
1. **Read the photo.** Note the document number, date, supplier, order number (PO), and for every line: description, printed quantity, unit, unit price, and the handwritten **Quantity Delivered**. "NIL", "0" or a dash means not delivered. A struck-out figure means read the corrected one. If a figure is truly unreadable, that line goes to the site.
|
||||
2. **Identity.** Compare with the candidate:
|
||||
- Wrong document number → `edit_document` (`documentNumber`, keep the misread in `alternates`).
|
||||
- Wrong order number → `edit_document` `orderReferences`.
|
||||
- Supplier / PO not linked → find the PO (`list_purchase_orders`, `get_purchase_order_detail`) and link it with `resolve_delivery_entities` (supplier id from the PO's `supplier_ref`).
|
||||
- Only link a PO you are sure of: same number (allowing obvious misreads), same supplier, same site, and the items are on it.
|
||||
3. **Not a delivery?**
|
||||
- A purchase order photo → `move_to_purchase_orders` (read every PO line from the photo).
|
||||
- A quotation, a duplicate of an already-posted slip, or another site's slip → `set_aside_document` with the kind and reason.
|
||||
- A hire contract → ask the site.
|
||||
4. **No PO in the system, or no PO on the slip** → `request_site_decision`: which PO, what was delivered, the value. Don't hunt further and don't guess a PO.
|
||||
5. **Quantities.** Where the reader's quantities differ from the photo, fix them with `update_delivery_candidate` (`items:[{lineIndex, qty}]`), then `process_delivery_candidate`.
|
||||
6. **Plan each line against the PO** (`get_purchase_order_detail`):
|
||||
- Units: book in the PO's unit. If the PO rate equals the slip price ÷ 6, the PO is per metre and a 6 m length (LE) is 6 m. Avidan pipes: ×6. If the rate equals the slip price, book the slip count.
|
||||
- Kits: when the PO has one line for a set (stub & flange, bolt set, gasket set), group the slip's component lines into one plan entry, e.g. `{"lines":[2,3],...}`. A kit is right when the components' slip amounts add up to about the PO rate × quantity.
|
||||
- Valuation: `usePoRate:true`. The slip price may differ from the PO rate; book at the PO rate and mention it in the report.
|
||||
- NIL lines close by themselves. Plan only lines with a delivered quantity.
|
||||
7. **Prepare** with `prepare_delivery` (same plan shape as `post_delivery`: `lines:[{lines:[n,...],confirmation:{confirmed:true,poItemId,quantity,unit,usePoRate:true,reason}}]`). Put the evidence in each `reason`, e.g. "handwritten 54 lengths; PO rate 144 = slip price per length".
|
||||
- Result `ready:true` → it is in Ready to post.
|
||||
- `over_po_needs_acceptance` → the slip takes a PO line over its ordered quantity. **Never set `acceptExcess` yourself.** Ask the site: "Slip X delivered N, PO has M outstanding: accept the extra, or is it for another PO?"
|
||||
- `waiting_for_site`, `preview_stale`, `lines_not_planned` → follow the hint in the error.
|
||||
8. **Double-check yourself** before moving on. `get_delivery_candidate` again and compare, line by line, the saved quantities (`reconciliation_preview.allocations[].quantity`, `.netAmount`) against the photo. Add up the nets: if the slip prints amounts, your total should match the slip's excl-VAT total within the price differences you noted. Anything that doesn't add up → undo by asking the site (`request_site_decision`) and say why in the report.
|
||||
|
||||
### D. Records to delete
|
||||
- Never delete. If something should go (a wrong alias, a duplicate record), use `request_deletion` with the reason.
|
||||
|
||||
## Rules
|
||||
- **Never book.** Do not call `post_delivery`, `post_delivery_line`, `correct_delivery_receipt`, `reassign_receipt` or `merge_suppliers`. If a posted receipt is wrong, put it in the report for the reviewer.
|
||||
- Never accept a quantity over the PO, never guess an unreadable figure, never link a PO you aren't sure of.
|
||||
- Fine, no attention needed: slip price differs from the PO rate (book at the PO rate and note it); a slip line covered by a PO set line (kit).
|
||||
- Ask the site (one clear question, with suggestions they can tap): missing PO, over the PO, unreadable quantity, delivered somewhere else, hire contracts, anything you'd be guessing.
|
||||
- Every write needs a fresh `operationId` (a new UUID v4) and a short `reason`. If a call fails, read the error's `hint`. Retry once with the same operationId only for a timeout or lock.
|
||||
|
||||
## Domain notes
|
||||
- Sites: The Hills (C26/09), Cedar Gate (C26/13). POs are numbered MEGCPO#### (sometimes printed MEGPO, MEDCPO, MEGCPC: all the same).
|
||||
- The reader often misreads numbers. Always confirm PO and document numbers on the photo. Seen: 9976 for 9076, 8165 for 9165, 3376 for 9376, "ID619312" for IO019312, "0007" for FH Chamberlain doc 07565729 (printed "0007/07565729": use 07565729).
|
||||
- **Avidan Trading cc** (Midrand Sales & Distribution): slip numbers IO + 6 digits. Prices excl VAT. The handwritten Quantity Delivered column is the receipt, not the printed Quantity. LE = 6 m length. Stub + back ring = "stub and flange" kit; bolts + washers (+ gasket) = bolt or gasket set.
|
||||
- **Raumix Aggregates**: weighbridge slips. Nett mass in kg ÷ 1000 = tonnes on the PO (G6 Sub Base, PO MEGCPO9165). The printed quantity *is* the receipt; a signature is enough.
|
||||
- **Global Precast**: slips count pipes; the PO is per metre. Pipe length is not printed (2.5 m is likely but unconfirmed): ask the site.
|
||||
- **Vula**: pipe lengths 2.5 m.
|
||||
- **FH Chamberlain** (hardware): counter-collected slips. **Sabrix** bricks are delivered direct on FH Chamberlain orders ("Bricks Dir Del").
|
||||
- **Hire All**: hire contracts (rate per day) are not deliveries. Ask the site.
|
||||
- **ARS14 / Asphaltic**: progress certificates (invoices) for asphalt on PO 9076; a "POSTED" stamp means accounts already processed it.
|
||||
- A photo of a PO uploaded as a delivery document → `move_to_purchase_orders`.
|
||||
|
||||
## Report (in addition to Foreman's standard sections)
|
||||
Add a section **"## For the reviewer"** with one table row per document you touched or looked at:
|
||||
|
||||
| Site | Document | Supplier | PO | Where it ended (Ready to post / Waiting for site / Set aside / Untouched) | What you changed (tool: what) | Prepared total excl VAT | Photo check (quantities you read) | Confidence (high / medium / low) + why |
|
||||
|
||||
Then **"## Posted receipts that look wrong"** (if any) and **"## Flagged for deletion"** (if any). Use exact numbers and ids (batch id and document id), so the reviewer can open each one directly.
|
||||
|
||||
## Examples
|
||||
- Avidan IO019340 (PO 9373): the reader read 12 junctions as NIL, 54 drainex as "SHL 4", 750 m mole barrier as 1800. The photo shows 12, NIL, 54, 3, 8, 750 → fix the quantities, then prepare: drainex 54 lengths at R144/length (PO rate = slip price per length).
|
||||
- Avidan IO019081 (PO 9256, 31 lines): 3 × 80mm gasket + 24 M16 bolts + 48 washers → one entry `{"lines":[5,6,7]}` on the 80mm gasket set, qty 3 (R336.42 on the slip vs R336.60 at the PO rate). Both UPVC pipe lines are NIL on the photo although the reader stored 4 and 31.
|
||||
- Raumix DQ0014666: printed order "#MEGCPO9165", read as 8165 → link PO 9165; 28,680 kg = 28.68 t.
|
||||
- Looks odd but fine: the 160mm end cap is R430 on the slip and R662 on the PO → book at the PO rate and note the difference.
|
||||
- Must go to the site: Global Precast 60084 counts 45 + 10 pipes against a per-metre PO.
|
||||
Loading…
Reference in a new issue