| name | kelly-audit |
| description | Personal App-in-Skill finance anomaly review desk that imports the three business tables — orders, invoices, payments/receipts (回款) — from CSV/JSON exports, flags anomalies with deterministic rules, and runs a human review queue with auditable decisions. Use when the user invokes $kelly-audit or /kelly-audit, mentions finance audit, order invoice payment reconciliation, 对账, 应收, 回款, 发票异常, receivables aging, overdue receivables, duplicate payments, missing invoices, amount mismatches, or anomaly review. |
Kelly Audit
Overview
Use this skill as Kelly's finance anomaly review desk for a finance lead, small-business owner, or bookkeeping team. It imports the three business tables — orders, invoices, and payments/receipts (回款) — from local CSV/JSON exports, cross-checks them with deterministic rules plus agent judgment, and surfaces anomalies in a file-backed App-in-Skill review queue. The skill imports, normalizes, and flags; the app is where a human confirms, assigns, or dismisses each anomaly; approved items become concrete follow-up actions (chase a receivable, reissue an invoice, flag to the accountant) executed by the agent outside the app.
This is different from kelly-money, which watches Kelly's own provider accounts: kelly-audit audits imported business documents against each other.
Default interaction mode: App UI. Unless the user explicitly asks for chat-only handling, check onboarding/config, refresh or load the local audit snapshot, start/reuse the local app with app/start.sh, and give the actual local URL. Use chat-only mode only when the user says "纯聊天", "chat only", "不要打开 UI", or similar.
App UI Screenshots
 |  |
Overview Finance audit desk with amount at risk, receivable aging bar, anomaly queue preview, and import history. | Anomaly queue Rule-flagged anomalies with the order-invoice-payment evidence chain and a drafted chasing email for approval. |
 |  |
Invoices Invoice ledger with due dates, paid amounts, days overdue, and match status. | Orders Normalized orders with invoice and payment status badges and linked anomaly indicators. |
Boundary
- Imports are local files only: the skill reads CSV/JSON exports the user provides, normalizes them, runs checks, and writes local handoff files. It never fetches business documents from remote systems on its own.
- The app reads and writes local files only and never touches any network beyond
127.0.0.1. It must not send emails, change ERP/bookkeeping records, move money, or mutate remote systems.
- Any outbound follow-up (a receivable-chasing email, a message to the accountant, a billing task) is approval-required through the anomaly queue and executed by the agent OUTSIDE the app via other skills (e.g. kelly-email), with the real result recorded back to
app/.data/execution_report.json.
- Treat all order/invoice/payment data as sensitive business data. Never commit imported business data:
config.local.json, env files, anything under app/.data/, sample exports with real customer names, and generated reports stay out of git.
First Run And Onboarding
On invocation, check app/.data/onboarding.json and private config readiness. If onboarding is absent/incomplete, guide setup before importing real tables.
Private config priority:
KELLY_AUDIT_CONFIG=/absolute/path/to/config.json
skills/kelly-audit/config.local.json
~/.config/kelly-audit/config.json
skills/kelly-audit/config.example.json as template only
Env priority:
- Existing environment variables
KELLY_AUDIT_ENV_FILE=/absolute/path/to/.env
- Repository root
.env
skills/kelly-audit/.env.local
~/.config/kelly-audit/.env
Onboarding asks for non-secret details only:
- Company profile: name, contact email, base currency, optional
fx_rates for mixed-currency books.
- Column mappings per table: which export header holds
order_no, customer, amount, invoice_no, due_date, payment_ref, and so on (see config.example.json).
- Tolerance rules:
days_to_invoice, amount_tolerance_pct, aging_buckets (default 30/60/90), duplicate_window_days.
When setup is complete and the user confirms, write app/.data/onboarding.json:
{
"completed": true,
"completed_at": "ISO timestamp",
"config_version": "1"
}
Local App
Start the review desk with:
skills/kelly-audit/app/start.sh
The app uses local HTTP on 127.0.0.1, preferring port 3000 through 4000, or KELLY_AUDIT_UI_PORT when set. The launcher reuses a running Kelly Audit server only when /api/state proves it is the same app (app: "kelly-audit"); otherwise it picks the next free port.
Required app views:
#/overview: audit command desk. Human-attention panel (anomalies needing a decision, high-risk amount at stake, overdue receivables total), KPI cards (orders/invoices/payments imported, matched %, open anomalies, receivable outstanding), a receivable aging buckets bar (inline SVG), and the recent import log.
#/orders and #/orders/<id>: normalized orders table — order no, customer, date, amount, currency, invoice status badge, payment status badge, linked anomaly. Detail shows the linked invoice(s) + payment(s) chain with per-link status.
#/invoices and #/invoices/<id>: invoices table — invoice no, order ref, customer, issue/due dates, amount, paid amount, days overdue, status. Detail shows matched payments, amount deltas, and notes.
#/anomalies (and #/anomalies/<id> deep links): the review queue with workflow states needs_review, changes_requested, approved, done, blocked. Each anomaly card shows the rule badge, severity, evidence (the exact rows plus the computed delta), the agent-drafted follow-up action (e.g. a receivable-chasing email draft or an internal request), an editable draft plus a Review note textarea, decision buttons (approve / request changes / block / dismiss = done), and a stable reference such as Anomaly #1.
#/settings: sanitized config only — company profile, tolerance rules, import column mappings, env readiness booleans, data provider, and onboarding state.
Demo mode:
?demo=1 opens a deterministic mock audit desk for documentation and screenshots.
?demo=overview, ?demo=orders, ?demo=invoices, ?demo=anomalies, and ?demo=detail (an amount-mismatch anomaly with its evidence chain) select named mock scenes.
lang=en or lang=zh forces UI chrome language; with lang=zh the demo content itself (customer names such as 明华贸易, anomaly titles, reasons, drafted emails) is meaningfully localized for Chinese screenshots.
- Demo API responses never read or write files under
app/.data/. Demo decisions stay in the browser only.
UI language: support English and Chinese chrome with Auto default (following the browser language) plus an explicit selector persisted locally. Keep imported document numbers and real business data untranslated.
File Contract
Read references/audit-schema.md before editing the app, scripts, or any generated audit JSON.
Primary local files:
app/.data/audit_snapshot.json: canonical snapshot — orders[], invoices[], payments[], anomalies[], matches[], metrics, import_log[] — generated by the scripts.
app/.data/decisions.json: user verdicts and notes keyed by anomaly id.
app/.data/agent_tasks.json: queued agent work — anomalies in changes_requested with the user's revision note.
app/.data/execution_report.json: latest execution results for approved anomalies.
app/.data/onboarding.json: onboarding completion marker.
app/.data/agent.lock: temporary lock while the skill is importing, checking, or executing. The app answers POST /api/decision with HTTP 423 while the lock exists.
config.local.json: private company/mapping/rules configuration, ignored by git.
Use scripts/validate_ui_schema.ts app/.data/audit_snapshot.json before relying on a snapshot in the UI. The app may show an empty setup state when no snapshot exists.
Import Workflow
- Detect mode. Default to App UI.
- Load private config. If only
config.example.json exists, enter onboarding.
- Ask which export files to import (orders, invoices, payments — any subset) and confirm the column mapping if the headers changed.
- Run the write path:
node skills/kelly-audit/scripts/import_tables.ts \
--orders /path/orders.csv --invoices /path/invoices.csv --payments /path/payments.csv
The script parses CSV (quoted fields included) or JSON arrays, applies the column mapping from config, normalizes dates/amounts/currencies, upserts by natural key (order_no / invoice_no / payment_ref) so re-imports are idempotent, recomputes derived statuses and metrics, and appends an import_log entry with per-file added/updated counts and row warnings. It refuses to run while agent.lock exists and takes the lock while writing.
- Surface import warnings (skipped rows, payments referencing unknown invoices) to the user instead of silently dropping them.
Check Workflow
- After every import (or on request), run the deterministic rule set:
node skills/kelly-audit/scripts/run_checks.ts
Rules, driven by config tolerances: missing_invoice (order without invoice after days_to_invoice days), amount_mismatch (invoice total vs order amount beyond amount_tolerance_pct), overdue_receivable (unpaid past due date, with 30/60/90+ aging buckets), duplicate (duplicate payment within duplicate_window_days, duplicate invoice number), unmatched_payment (payment matching no invoice), irregular_entry (credit note without an original, negative payments).
- Anomaly ids are stable (
anom-<rule>-<key>), so re-runs upsert instead of duplicating; existing statuses, refs, decisions, and user-edited drafts are preserved; anomalies whose condition cleared are auto-resolved to done.
- The agent may then improve on the deterministic output: sharpen titles/reasons, localize, and refine the drafted follow-up (chasing email, billing request, accountant note) — keeping ids and evidence intact.
- Validate with
scripts/validate_ui_schema.ts, start/reuse the UI, and send the user to #/anomalies.
Decisions And Agent Tasks Loop
- The user reviews at
#/anomalies: approve, request changes (with a note), save an edited draft, block, or dismiss. Decisions persist through POST /api/decision into decisions.json (423 while locked).
- Poll
app/.data/agent_tasks.json for changes_requested items, revise the anomaly draft per the note, and return the item to needs_review.
- On explicit user request to execute, run
scripts/execute_decisions.ts (dry-run by default; --apply marks items ready_for_agent). It re-checks the lock and decisions and writes execution_report.json entries with concrete operations — chase_receivable (with the drafted email handoff), reissue_invoice, flag_to_accountant — and target document ids. No external side effects either way.
- The agent then performs the approved follow-ups outside the app (send the chasing email via the email skill, open the billing/accountant task), records real results in
execution_report.json, and executed anomalies show as done.
Safety Defaults
- Treat every outbound message, ERP/bookkeeping mutation, refund, and credit-note change as approval-required via the anomaly queue.
- Store only the minimum normalized fields the review desk needs; keep raw exports outside git and reference them by path in
import_log.
- Use stable ids and natural-key upserts so repeated imports, checks, and executions are idempotent.
- Never expose secrets or full customer datasets through
/api/state, logs, or reports; the settings view shows env readiness booleans and column mappings only.
- If the tables disagree in a way no rule covers, add a snapshot warning and ask the user — do not invent corrections to make the books balance.