In the billing-reversals case, one invoice in six on a real wholesaler's ledger was later credited back, and a model could say which ones would be. This engine is the other half: the seven questions a credit note must answer before it exists — which invoice, how much is still open on it, why, has this been asked already, how often has this customer been credited, who may say yes, and is the goodwill budget spent. It is running below, in your browser, on 500 requests you can make as generous as you like.
Every credit note is a decision that someone did not have to defend. The invoice was wrong, so credit it; the customer was unhappy, so credit it; the salesperson promised, so credit it. Each one is small and each one is reasonable, and the sum is a leak that never shows up as a loss because it was never booked as revenue that stayed. In the billing-reversals case the reversals were found after the fact, tied back to the invoices they unwrote, and a model learned to predict them at the moment of invoicing. The Credit Note Gate is the SEAL that follows the TRACE: a credit note cannot exist until seven questions are answered on the request itself, in a fixed order, with the first failure winning — so the note that does get raised carries its own explanation, and the one that does not carries the sentence that stopped it.
The engine is deliberately boring: no model of which customers deserve goodwill, no fuzzy matching, no threshold tuned by feel. Each gate is a sentence a finance head can read and disagree with, the limits are numbers printed on the sliders, and the goodwill cap is arithmetic on the requester's own book. That is what makes a refusal survivable: when the gate says no, the requester can see which sentence said it and what would have passed.
| GATE | RULE | WHAT IT DOES |
|---|---|---|
| G1 · an invoice | The request must reference an invoice | Else REFUSED · NO_INVOICE. A credit against nothing is the purest form of the leak. |
| G2 · room on it | Amount ≤ what is still open on the invoice (earlier credits already deducted) | Else REFUSED · OVER_REMAINING. You cannot give back more than was billed. |
| G3 · a reason | A reason code is present: PRICING_ERROR · SHORT_SHIPPED · QUALITY · GOODWILL · DUPLICATE_BILLING | Else HELD · NO_REASON — back to the requester, not refused. The word is the point. |
| G4 · not already asked | No earlier request on the same invoice with an amount within 2% inside the duplicate window (default 10 days) | Else REFUSED · DUPLICATE, with the earlier request named. |
| G5 · not too often | The customer has received fewer than N − 1 credit notes in the last 30 days (default N = 3; counts notes actually issued) | Else HELD · FREQUENCY — a customer credited every fortnight is a pricing or a quality problem, not a credit problem. |
| G6 · who may say yes | ≤ ₹5,000 AUTO · ≤ ₹50,000 MANAGER · above FINANCE_HEAD | The tier, not the answer. AUTO goes out with no human; the rest wait for one. |
| G7 · the goodwill budget | A GOODWILL credit may not take the requester's goodwill credits this quarter above 1% of the invoiced value in their name | Else HELD · GOODWILL_CAP. Goodwill is a budget, and the budget belongs to the person spending it. |
| The approver | Answers within 24 h with p = 0.85, else the request ESCALATES one level and is answered there in 24–72 h; grants with p = 0.9 PRICING_ERROR · 0.9 SHORT_SHIPPED · 0.8 QUALITY · 0.95 DUPLICATE_BILLING · 0.5 GOODWILL | The synthetic approver. In life the probabilities are the approvers' own history. Declined → nothing is credited. |
| The ledger | An approved credit reduces the invoice's remaining | So the next request on that invoice meets G2 with less room. The gate remembers. |
| ₹ prevented | Refused + declined + held-not-yet-approved value | The number the page leads with. Holds are money that is waiting for a sentence, not money that is gone. |
| Tie-out | 500 = auto + approved + declined + escalated + held + refused; ₹ requested = ₹ credited + ₹ prevented | If either breaks, the quarter's credit report is not published. |
# the gate, in this order — first failure wins (engine.py) if Q["f_no_invoice"]: Q["decision"] = "REFUSED"; Q["code"] = "NO_INVOICE" # G1 elif Q["f_over"]: Q["decision"] = "REFUSED"; Q["code"] = "OVER_REMAINING" # G2 elif Q["reason"] == "": Q["decision"] = "HELD"; Q["code"] = "NO_REASON" # G3 · to the requester elif Q["f_dup"]: Q["decision"] = "REFUSED"; Q["code"] = "DUPLICATE" # G4 else: n30 = credit notes this customer received in the last 30 days if n30 + 1 >= freq_n: Q["decision"] = "HELD"; Q["code"] = "FREQUENCY" # G5 else: Q["tier"] = tier_of(Q["amount"], auto_limit, manager_limit) # G6 · the tier if Q["reason"] == "GOODWILL" and gw_credited[r] + Q["amount"] > cap * inv_value[r]: Q["decision"] = "HELD"; Q["code"] = "GOODWILL_CAP" # G7 elif Q["tier"] == "AUTO": Q["decision"] = "AUTO" else: answered = rng2.random() < SLA_P # within 24 h with p 0.85 granted = rng2.random() < GRANT_P[Q["reason"]] # 0.9 · 0.9 · 0.8 · 0.95 · 0.5
Run the quarter to see what the gate stops.
Two things to try. Switch the gate off and the big number turns into what gets credited when nobody asks: the same 500 requests, ₹7.4 lakh of them against no invoice at all, ₹2.3 lakh asked twice, and ₹2.7 lakh credited beyond what was ever billed. Then drag the goodwill cap down to 0.5%: at 1% it never fires on this stream, because the frequency guard and a 50-50 approver catch goodwill first; at 0.5% it starts naming requesters. A cap that never fires is not wrong — it is a budget nobody has reached yet — but it is a slider, not a constant, because the day someone reaches it is the day you want to know.
| WHEN | WHAT HAPPENS | WHO SEES IT |
|---|---|---|
| At request time | G1–G5 run inside the ticket the moment it is raised. A refusal names the gate and the earlier request it clashes with; a hold goes back to the requester or to review with the sentence that held it. | The requester, in under a second, with what would have passed. |
| Within 24 h | The approver at the tier answers. Unanswered requests escalate one level and are counted as escalations against the approver. | The manager, then the finance head. The escalation count is how you find the approver who is the bottleneck. |
| Nightly | Approved credits are posted and the invoice's remaining is reduced; the day's decisions are tied out: requests = auto + approved + declined + escalated + held + refused. Any gap → no post. | The controller. A tie-out failure is the engine finding a bug in itself. |
| Weekly | The goodwill ledger by requester against their cap, the frequency holds by customer, the duplicates caught. A customer held twice for frequency in a month is handed to pricing or quality, not to credit control. | Finance and sales, with the by-requester table on the table. |
| Quarterly | The caps reset. The approval rate by reason and the ₹ prevented are the two numbers leadership sees. Limits move only when that page moves. | Leadership — the WATCH stage of the Leak Ledger. |
A credit note that cannot explain itself should not exist. The value is not the ₹47 lakh this stream stopped in a quarter — most of it is holds, money waiting for a reason, and much of it will be credited once the reason arrives. The value is that every credit note that does get raised carries an invoice, a remaining balance, a reason, a tier and a budget, and every one that does not carries the sentence that stopped it. Make the gates readable, the limits sliders, the goodwill a budget with a name on it, and the tie-out refuse to lie, and the credit note stops being the leak.
Credit notes nobody can explain? A credit note gate is a two-to-four-week SEAL: your reason codes, your tiers, your goodwill budgets — running inside the ticket, with a tie-out that refuses to post a credit that does not add up.
Start with a TRACE → engine.py README results.json The case it came from →